[ https://issues.apache.org/jira/browse/THRIFT-2441?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14390581#comment-14390581 ]
James E. King, III commented on THRIFT-2441: -------------------------------------------- Let's discuss a potential solution to this issue: 1. Create transport/TInterruptable, providing interrupt(), returns a boolean indicating if interrupt is supported. 2. Change TServerTransport to inherit from interrupt(). 3. Change TTransport to inherit from interrupt(). 4. Add a mechanism in TSocket that is similar to TServerSocket for interruption. Each client TSocket behavior will remain fully encapsulated. Possibly extract this common shared behavior to another class. 5. Change TSocket::read to select and recv, and handle interrupt in much the same way that TServerSocket does. 6. Fix up each TServer to properly handle stop() by ending its serve(), which must guarantee that the server transport and all tracked client transports/tasks are interrupted and then closed before returning. Stop will therefore happen like this (with TThreadedServer): 1. TThreadedServer implements stop() which sets a stop flag and then calls interrupt() on the TServerTransport. This is existing behavior. 2. stop() joins to the TThreadedServer serve() thread. stop() will not return until things have actually stopped. This is new behavior. 3. The interrupt unblocks the TServerTransport accept and that in turn throws a TTransportException of type INTERRUPTED. This is existing behavior. 4. TServerTransport::serve() falls out of the processing loop. In handling the INTERRUPTED if the stop_ flag is set, serve() proceeds to teardown. This is new behavior. 5. serve() teardown iterates each Task and interrupts it. This means each Task is a TInterruptable, and interrupt is asynchronous. This is new behavior. 6. serve() blocks on a drain event. This is existing behavior. 7. Each Task blocked in recv is interrupted and throws a TTransportException of type INTERRUPTED. This is new behavior. 8. Each Task falls out of its processing loop and closes the transport. When the last task disappears, the drain event is set. This is existing behavior. 9. serve() unblocks on the drain event and returns. 10. TThreadedServer::stop joins as serve() returns and stop is complete. Discussion points: * Did not provide a way to maintain the current behavior of blocking stop() until all clients disconnect. I view this as a defect, however it is the current behavior. Is it a requirement to be able to continue to provide this behavior? * Each TSocket will have its own SOCKET_PAIR to facilitate interruption. This is fully encapsulated, but it also requires more resources. Would this count as 3 open file descriptors per client instead of one? Is that acceptable, or should the TServer provide each TTransport with a common way to be interrupted that is transport-agnostic? That would be substantially more work. > Cannot shutdown TThreadedServer when clients are still connected > ---------------------------------------------------------------- > > Key: THRIFT-2441 > URL: https://issues.apache.org/jira/browse/THRIFT-2441 > Project: Thrift > Issue Type: Bug > Components: C++ - Library > Affects Versions: 0.9.1 > Reporter: Chris Stylianou > Assignee: Ben Craig > > When calling stop() on the TThreadedServer no interrupts are sent to the > client threads. This means the stop() call blocks on tasksMonitor.wait() > until all client naturally disconnect. > How can we tell the client thread connections to close/exit during the > TThreadedServer::stop() call? -- This message was sent by Atlassian JIRA (v6.3.4#6332)