Hello
I wanted to make use of IsCancelled in async server to stop processing requests that were cancelled by user.
In order to use ServerContext::IsCancelled method I had to call ServerContext::AsyncNotifyWhenDone first.
And then some problems occurred.
1. I took a greeter_async_server.cc from grpc cpp examples and added ctx.AsyncNotifyWhenDone(this);
If I drop deleting the CallData object in FINISH state it turns out that there are 2 events from CompletionQueue at the end of request processing:
Proceeding call 0x4e25550 with status 0
Proceeding call 0x4e25550 with status 1
Proceeding call 0x4e25550 with status 2
Proceeding call 0x4e25550 with status 2
So I think that's why the server crashes - with the first FINISH state the CallData is being freed and the second event cannot operate on deleted object.
2. If there're always 2 events from CompletionQueue at the end I can introduce new transitive state of CallData.
Then the request is processed through all 4 states (and CallData is freed only once at the last one of them):
Proceeding call 0x4e25550 with status 0
Proceeding call 0x4e25550 with status 1
Proceeding call 0x4e25550 with status 2
Proceeding call 0x4e25550 with status 3
Almost OK...
Without AsyncNotifyWhenDone it works really great, but after enabling it, those 2 events sent at the end of request processing, can be received by 2 seperate threads, leading to race condition while changing the state of CallData and not being freed at all (CallData maintains in FINISH state and never proceeds to CLEANUP state).
[140135346489088] Proceeding call 0x7f73b800a090 with status 0
[140135346489088] Proceeding call 0x7f73a8000b20 with status 1
[140135346489088] Proceeding call 0x7f73a8000b20 with status 2
[140134984972032] Proceeding call 0x7f73a8000b20 with status 3
^^^^^^^^^^^^^^^^^
different thread
Worst case scenario looks like that:[140135346489088] Proceeding call 0x7f73b800a090 with status 0
[140135346489088] Proceeding call 0x7f73a8000b20 with status 1
[140135346489088] Proceeding call 0x7f73a8000b20 with status 2
[140134984972032] Proceeding call 0x7f73a8000b20 with status 2
2 different threads modify CallData's status at the same time resulting not being freed at all.
What can be done to safely free CallData while getting additional events from CompletionQueue after enabling AsyncNotifyWhenDone?
--
Best regards
Przemysław Sobala