Python server not respecting timeout?

37 views
Skip to first unread message

liburdi...@gmail.com

unread,
Mar 19, 2019, 12:48:53 PM3/19/19
to grpc.io
I want to verify some behavior in the Python code -- are timeouts only respected while receiving requests and not after requests have been received (but RPC is not finished)? Here's an example that uses a client-streaming RPC:

Server pseudo-code:

    def Server(self, request_iterator, context):
        for request in request_iterator:
            pass

        for _ in range(10):
            time.sleep(1)

        print(context.is_active())
        print('still running!')
        return test_pb2.Response()


Client pseudo-code:

    def yielder():
        for _ in range(20):
            yield test_pb2.Request()

    stub = test_pb2_grpc.TestStub(channel)
    response = stub.Server(yielder(), timeout=5)
    print(response)


What happens is that the server will receive all the requests streams and while performing an operation, the timeout will pass and context will be inactive -- however, the RPC never aborts (i.e. the server will print 'still running!'). Is this intended behavior? I would expect that the server to stop processing after the timeout has elapsed.

liburdi...@gmail.com

unread,
Mar 19, 2019, 1:32:09 PM3/19/19
to grpc.io
In addition, it seems like the callback functionality should be able handle this through something like this ...

Server pseudo-code:

    def Server(self, request_iterator, context):
        context.add_callback(context.cancel())
        for request in request_iterator:
            pass

        for _ in range(10):
            time.sleep(1)

        print(context.is_active())
        print('still running!')
        return test_pb2.Response()

... however, this immediately cancels the RPC, which seems to disagree with the intended behavior described in the documentation: https://grpc.io/grpc/python/grpc.html#grpc.RpcContext.add_callback

Lidi Zheng

unread,
Mar 19, 2019, 3:42:00 PM3/19/19
to Josh Liburdi, grpc.io
Your second post has a tiny typo I think. To pass a Python function as parameter, you don't need the parentheses:

        context.add_callback(context.cancel)

Also, the callbacks added to the context will only execute after the gRPC termination. By that time, the "context.cancel" will be a no-op.

About your first question regarding to deadline. The deadline exceeded in client-side will cancel the server-side request, but it is not cancelled automatically since there is no (legit) way in Python to terminate a running thread. If you would like to terminate your server task, please explicitly check the "is_active()" function in servicer context.

Hope this will answer your questions :)






--
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+u...@googlegroups.com.
To post to this group, send email to grp...@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/a9d19d24-75d0-459f-ac51-c15a4d02422e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

liburdi...@gmail.com

unread,
Mar 21, 2019, 8:44:17 PM3/21/19
to grpc.io
Thanks for the feedback, all of that makes sense. Using your feedback, I think I came across a design that will work for my application, but I'd be curious to hear your feedback on it (especially the potential post-forking of subprocesses): https://github.com/grpc/grpc/issues/16001#issuecomment-475439137

It's manageable and convoluted, my primary concern is if post-forking subprocesses outside the scope of the gRPC servicer will cause any issues with the gRPC servicer itself. 

Lidi Zheng

unread,
Mar 21, 2019, 9:20:16 PM3/21/19
to Josh Liburdi, grpc.io
Replied under your GitHub comment.

Reply all
Reply to author
Forward
0 new messages