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