[ 
https://issues.apache.org/jira/browse/WSCOMMONS-402?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12646616#action_12646616
 ] 

Andreas Veithen commented on WSCOMMONS-402:
-------------------------------------------

Catching the InterruptedIOException and breaking to loop is indeed the simplest 
solution to the problem. However, I would prefer that SimpleHttpServer#destroy 
directly closes the ServerSocket without trying ExecutorServide#shutdownNow. 
The reason is that this would work on all platforms in the same way and on JVMs 
of the first type it would avoid spending unnecessary time in 
ExecutorServide#awaitTermination. Actually on this type of platform, the test 
cases for the HTTP transport probably spend more time waiting than to execute 
the actual tests...

> SimpleHttpServer doesn't shut down cleanly on some platforms
> ------------------------------------------------------------
>
>                 Key: WSCOMMONS-402
>                 URL: https://issues.apache.org/jira/browse/WSCOMMONS-402
>             Project: WS-Commons
>          Issue Type: Bug
>         Environment: minotaur.apache.org: Java HotSpot(TM) 64-Bit Server VM 
> (build diablo-1.5.0_07-b01, mixed mode)
>            Reporter: Andreas Veithen
>            Priority: Minor
>
> Different JVM implementations show different behaviors when Thread#interrupt 
> is called on a thread that is blocked in ServerSocket#accept:
> 1. Most JVMs only set the interrupted flag on the thread but don't trigger an 
> exception.
> 2. Other JVMs cause a java.io.InterruptedIOException to be thrown out of 
> ServerSocket#accept but don't set the interrupted flag.
> On JVMs that have behavior 1, when calling SimpleHttpServer#destroy, the 
> sequence of events is as follows:
> 1. SimpleHttpServer#destroy calls ExecutorServide#shutdownNow.
> 2. ExecutorServide#shutdownNow calls Thread#interrupted on the thread running 
> DefaultConnectionListener (and blocked in ServerSocket#accept). This sets the 
> interrupted flag, but doesn't cause an exception.
> 3. SimpleHttpServer#destroy calls ExecutorServide#awaitTermination which will 
> only return after the specified timeout (because the 
> DefaultConnectionListener thread is still running).
> 4. SimpleHttpServer#destroy calls DefaultConnectionListener#destroy which 
> closes the ServerSocket.
> 5. ServerSocket#accept throws an exception. The catch block in 
> DefaultConnectionListener#run checks the interrupted flag and since it is 
> set, the method exits, terminating the thread.
> Except for step 3, this approach is correct and results in a clean shutdown.
> On JVMs having the other behavior, the sequence of events is completely 
> different:
> 1. SimpleHttpServer#destroy calls ExecutorServide#shutdownNow.
> 2. ExecutorServide#shutdownNow calls Thread#interrupted on the thread running 
> DefaultConnectionListener (and blocked in ServerSocket#accept).
> 3. An InterruptedIOException is thrown out of ServerSocket#accept. Since the 
> interrupted flag is not set, the exception is handed over to the 
> DefaultConnectionListenerFailureHandler.
> 4. DefaultConnectionListenerFailureHandler#failed returns true and 
> DefaultConnectionListener will immediately reenter ServerSocket#accept.
> 5. SimpleHttpServer#destroy calls ExecutorServide#awaitTermination which will 
> only return after the specified timeout (because the 
> DefaultConnectionListener thread is still running).
> 6. SimpleHttpServer#destroy calls DefaultConnectionListener#destroy which 
> closes the ServerSocket.
> 7. ServerSocket#accept throws an exception. Since the interrupted flag is 
> still not set, the exception is again handed over to 
> DefaultConnectionListenerFailureHandler#failed which instructs the 
> DefaultConnectionListener to retry.
> 8. Since the original server socket is now closed, 
> DefaultConnectionListener#run will create a new ServerSocket and open the 
> port again. It then blocks in ServerSocket#accept.
> 9. SimpleHttpServer#destroy shuts down the request processors and exits.
> As can be seen this leaves the HTTP port open and SimpleHttpServer doesn't 
> shut down cleanly.
> The problem can be reproduced by running the transport tests on minotaur 
> (peope.apache.org). The HTTP tests will fail with an "Address already in use" 
> error because at some point a test case tries to start a different HTTP 
> server on the port that is still used by the SimpleHttpServer instance that 
> didn't shut down cleanly.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to