Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: Added changes to make ServerImpl.internalClose() thread-safe #11924

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

vinodhabib
Copy link
Contributor

core: Added changes to make ServerImpl.internalClose thread-safe

Fixes: #3746

@vinodhabib vinodhabib marked this pull request as ready for review March 4, 2025 07:06
@vinodhabib
Copy link
Contributor Author

vinodhabib commented Mar 4, 2025

Created this new PR with required changes along with Review points fixes as part of Existing PR #11864 which needs to close as duplicate once this PR merged.

@vinodhabib vinodhabib marked this pull request as draft March 7, 2025 11:45
@vinodhabib vinodhabib marked this pull request as ready for review March 7, 2025 11:49
@@ -581,6 +586,7 @@ public void close(Status status, Metadata trailers) {
// clientStreamListener.closed can trigger clientStream.cancel (see code in
// ClientCalls.blockingUnaryCall), which may race with clientStream.serverClosed as both are
// calling internalCancel().
closeCalled = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eric had commented that the stream implementation should handle whether close had already been called but this PR is doing it in the InProcessTransport.

Copy link
Contributor Author

@vinodhabib vinodhabib Mar 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and moved the changes to AbstractServerStream

Copy link
Contributor

@kannanjgithub kannanjgithub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs work.

@vinodhabib
Copy link
Contributor Author

Needs work.

Fixed the Review comments and PR is Ready for your Re-review.

@@ -120,6 +121,7 @@ public final void deliverFrame(

@Override
public final void close(Status status, Metadata trailers) {
Preconditions.checkState(!closeCalled, "call already closed");
Preconditions.checkNotNull(status, "status");
Preconditions.checkNotNull(trailers, "trailers");
if (!outboundClosed) {
Copy link
Contributor

@kannanjgithub kannanjgithub Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If internalClose was called before, outboundClosed would have been set to true and any further calls to close() from anywhere else already skips over if outboundClosed is true. Your changes here don't seem to be achieving anything extra.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to make the check apply for usages of stream in ServerCallImpl (application thread usages of the stream) if the stream had already been closed. Refer comment. Also we should not need to add another field to track the stream closed status since there is already an outboundClosed field and this should be able to be used for such checks.

@@ -120,6 +121,7 @@ public final void deliverFrame(

@Override
public final void close(Status status, Metadata trailers) {
Preconditions.checkState(!closeCalled, "call already closed");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is precondition the right thing to do or will logging an error message do? With an example callstack for close

close:123, AbstractServerStream (io.grpc.internal)            
closeInternal:227, ServerCallImpl (io.grpc.internal)
close:213, ServerCallImpl (io.grpc.internal)
onCompleted:395, ServerCalls$ServerCallStreamObserverImpl (io.grpc.stub)
sayHello:104, HelloWorldServer$GreeterImpl (io.grpc.examples.helloworld)
invoke:285, GreeterGrpc$MethodHandlers (io.grpc.examples.helloworld)
onHalfClose:182, ServerCalls$UnaryServerCallHandler$UnaryServerCallListener (io.grpc.stub)
halfClosed:356, ServerCallImpl$ServerStreamListenerImpl (io.grpc.internal)
runInContext:861, ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed (io.grpc.internal)  
run:37, ContextRunnable (io.grpc.internal)
run:133, SerializingExecutor (io.grpc.internal)                             
runWorker:1144, ThreadPoolExecutor (java.util.concurrent)
run:642, ThreadPoolExecutor$Worker (java.util.concurrent)
runWith:1596, Thread (java.lang)
run:1583, Thread (java.lang)

Failed precondition will cause the exception to be caught at runInContext:861, ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed and again call internalClose and rethrow the exception which then will be caught and logged in run:133, SerializingExecutor.
If the application continues to attempt to write messages these steps will keep repeated for each attempt and the application is not going to come to know of it anyway. It may be better to just write an error log instead. @ejona86 to confirm.

Copy link
Contributor

@kannanjgithub kannanjgithub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review comments.

@kannanjgithub
Copy link
Contributor

We discussed internally and concluded this issue is too complex to get it done by xWF. Please stop working on this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make ServerImpl's internalClose thread-safe
2 participants