I'm not sure if TryCancel is the easy way to stop a stream. Calling WritesDone() on client and Finish on server is equally simple.
In any case, the recommended way is to do TryCancel() only when you no longer see a point in continuing the call. Also TryCancel is a best-effort call..so Once you do TryCancel, you must still do a CQ next (and see if it returns a failure) to make sure the call is actually cancelled. Sree On Jul 12, 2017 12:59 PM, "yihao yang" <yangyihao1...@gmail.com> wrote: Hi, Sree, Thank you for the reply. It's very helpful. I still want to know what is the best practice for the TryCancel in both server and client side. I use it because I can easily stop both the stream read and write through this interface. If the client side does not care about the final status of server, I think TryCancel is more convenient, right? Is there any side-effects of TryCancel? Thanks, Yihao On Tue, Jul 11, 2017 at 5:05 PM, 'Sree Kuchibhotla' via grpc.io < grpc-io@googlegroups.com> wrote: > On async streams on servers, you simple call stream->Finish(const Status > <https://cs.corp.google.com/piper///depot/google3/third_party/grpc/google_specific/include/grpc%2B%2B/impl/codegen/status.h?l=24&ct=xref_jump_to_def&gsn=Status&rcl=161340537> > & > <https://cs.corp.google.com/piper///depot/google3/GENERATED/figments/cpp/LValueRefTo/Const/start-with-gr/grpc/class-Status.cc?l=3&ct=xref_jump_to_def&gsn=%26&rcl=161340537> > status > <https://cs.corp.google.com/piper///depot/google3/third_party/grpc/include/grpc%2B%2B/impl/codegen/async_stream.h?l=675&gs=cpp%253Agrpc%253A%253Aclass-ServerAsyncWriterInterface%253C%25231%253E%253A%253AFinish(const%2Bgrpc%253A%253AStatus%2B%2526%252C%2Bvoid%2B*)%253A%253Aparam-status%2540google3%252Fthird_party%252Fgrpc%252Finclude%252Fgrpc%252B%252B%252Fimpl%252Fcodegen%252Fasync_stream.h%253A28320%257Cdecl&gsn=status&ct=xref_usages>, > void* > <https://cs.corp.google.com/piper///depot/google3/GENERATED/figments/cpp/PointerTo/void.cc?l=3&ct=xref_jump_to_def&gsn=*&rcl=161340537> > tag > <https://cs.corp.google.com/piper///depot/google3/third_party/grpc/include/grpc%2B%2B/impl/codegen/async_stream.h?l=675&gs=cpp%253Agrpc%253A%253Aclass-ServerAsyncWriterInterface%253C%25231%253E%253A%253AFinish(const%2Bgrpc%253A%253AStatus%2B%2526%252C%2Bvoid%2B*)%253A%253Aparam-tag%2540google3%252Fthird_party%252Fgrpc%252Finclude%252Fgrpc%252B%252B%252Fimpl%252Fcodegen%252Fasync_stream.h%253A28334%257Cdecl&gsn=tag&ct=xref_usages>) > to send the final status (and do a Cq->next) and close the stream (from > server side). On the client side, the client would do a > cli_stream->Read() Which would fail (since the stream is closed by > server). The client would then do a cli_stream->Finish() to get the > status sent by the server. That is the normal sequence. You really do not > need to do TryCancel(). Just FYI, the following is the typical sequence > of events on a Bidi Stream on client and server side: > > Sequence of events on the client side: > 1) Create a client bidi stream "cli_stream" > 2) Do one or more cli_stream->Read() and cli_stream->Write() (need to > match > 3) "half-close" i.e close the stream (for writes) from client side by > doing: cli_stream->WritesDone(); > 4) Note: At this point, cli_stream->Read() will still work (since the > server has not closed the stream from its side) > 5) Once the server closes the stream from it's side (cli_stream->Read() > would return false) > 6) Do cli_stream->Finish() to get the status from the server > > Sequence of events on the server side: > 1) Create a server bidi stream "server_stream" > 2) Do one more server_stream->Read() and server_stream->Write() (need to > match with step #2 in client side) > 3) Once client does a close from its side, server_stream->Read() would > return "false" > 4) Note: At this point server_stream->Write() will still work. > 5) Now close the writes stream from server side and send a status by > calling server_stream->Finish() > --- > > Now to specifically answer your question: > >>> If I want to close from the server side by TryCancel() and followed by > a Finish() will this cause any problem? > If for whatever reason you decided to do TryCancel() first on server > followed by server_stream->Finish(), it is a race-condition (The > TryCancel() API is best-effort API and doesn't guarantee the stream will be > cancelled right-away. So it is possible that operation may fail and the > stream wasn't cancelled by the time you called Finish(). In this case, > Finish() would succeed and you get a success event in CQ. If not, i.e if > stream cancel happened by the time you called Finish(), then you get a > failure event in CQ (with status CANCELLED - I think..i am not sure of > exact status code). > > >>>After what I called stream->Finish(status), will this event return in > the CQ if the client is closed already? > Well, from the sequence of events I posted above, if the client did a > "half-close" by doing a cli_stream->WritesDone(), then its perfectly safe > for server to do stream->Finish(status). > However, if the client closed the stream by calling "TryCancel", then > again its a race condition. If the cancellation reached server, then > stream->Finish(status) will fail (i.e a failed event with return on CQ) > else, it would succeed if the cancellation did not happen yet. > > Hope this helps, > Sree > > On Sunday, July 2, 2017 at 2:57:47 PM UTC-7, yihao yang wrote: >> >> Hi, Sree: >> >> Do you know what if the stream is an async bidi stream? If I want to >> close from the server side by TryCancel() and followed by a Finish(), will >> this cause any problem? After what I called stream->Finish(status), will >> this event return in the CQ if the client is closed already? >> >> Thanks, >> Yihao >> >> 在 2017年6月27日星期二 UTC-7下午4:18:43,Sree Kuchibhotla写道: >>> >>> Sorry for the late response. >>> >>> There is no special method to 'close' the BiDi streams. On the server, >>> just returning a status would mean that you are done with the stream. >>> >>> However, in the example you have given, you seem to be calling just 1 >>> read. Since you mentioned you are noticing a memory leak, I was >>> wondering...are you sure that you are reading all the messages that client >>> is sending ? >>> >>> You don't have to really check 'context->IsCancelled()' here. >>> stream->Read() has a return value. It returns 'true' as long as there is a >>> message to read from the client. stream->Read() returns a 'false' either >>> when the client gracefully finished the writes (by calling >>> stream->WritesDone() and stream->Finish() on the client side) or if the >>> client cancelled the RPC or there was some other error.. >>> >>> So I recommend you rewrite your loop as >>> >>> Status BidiServiceImpl::BiDiStreamingRpc(...) >>> { >>> .. >>> while (stream->Read(&req)) { >>> getRest(resp); >>> stream->Write(resp); >>> } >>> >>> // You can check context->IsCancelled() here if you >>> // are interested in whether the RPC was cancelled >>> >>> return Status(..) >>> } >>> >>> thanks, >>> Sree >>> >>> >>> On Monday, May 1, 2017 at 10:45:37 PM UTC-7, rajeev...@rediffmail.com >>> wrote: >>>> >>>> >>>> Hello, >>>> >>>> Is there a way to close down BiDi streaming gracefully from C++ server >>>> thread (pthr) when c++ client gets aborted? When I simply return from Bidi >>>> streaming rpc based on IsCancelled() I observe memory leaks. >>>> >>>> Here is the sample code >>>> >>>> >>>> Status BiDiServiceImpl::BiDiStreamingRpc(::grpc::ServerContext* >>>> context, ::grpc::ServerReaderWriter< BiDiResponse, BiDiRequest>* stream) >>>> { >>>> BiDiRequest req; >>>> BiDiResponse resp; >>>> >>>> stream->Read(&req); >>>> while(context->IsCancelled() == false) >>>> { >>>> getResp(resp); >>>> stream->Write(resp); >>>> } >>>> return(Status(Status::GRPC_OK, "")); >>>> } >>>> >>>> >>>> Thanks >>>> Rajeev >>>> >>>> -- > You received this message because you are subscribed to a topic in the > Google Groups "grpc.io" group. > To unsubscribe from this topic, visit https://groups.google.com/d/to > pic/grpc-io/AlwaSuDTcoM/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > grpc-io+unsubscr...@googlegroups.com. > > To post to this group, send email to grpc-io@googlegroups.com. > Visit this group at https://groups.google.com/group/grpc-io. > To view this discussion on the web visit https://groups.google.com/d/ms > gid/grpc-io/dc1a9aeb-5f8c-4291-a755-9b3db1d063ca%40googlegroups.com > <https://groups.google.com/d/msgid/grpc-io/dc1a9aeb-5f8c-4291-a755-9b3db1d063ca%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "grpc.io" group. To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+unsubscr...@googlegroups.com. To post to this group, send email to grpc-io@googlegroups.com. Visit this group at https://groups.google.com/group/grpc-io. To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/CALRi9QfJ%3DYoRm2iSmDD%2BHGR%2BGQbgW%2BqfqADY_OkQ8OSFufXkUA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.