[ 
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)

Reply via email to