Skip to content

Commit dbad4a2

Browse files
committed
tweaked WebsocketServer.stop to perform a graceful shutdown
1 parent 2b0bb8d commit dbad4a2

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

‎src/main/java/org/java_websocket/server/WebSocketServer.java‎

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,13 @@ public void start(){
195195
* If this method is called before the server is started it will never start.
196196
*
197197
* @param timeout
198-
* Specifies how many milliseconds shall pass between initiating the close handshakes with the connected clients and closing the servers socket channel.
198+
* Specifies how many milliseconds the overall close handshaking may take altogether before the connections are closed without proper close handshaking.<br>
199199
*
200200
* @throws IOException
201201
* When{@link ServerSocketChannel}.close throws an IOException
202202
* @throws InterruptedException
203203
*/
204-
publicvoidstop( inttimeout ) throwsIOException , InterruptedException{
204+
publicvoidstop( inttimeout ) throwsInterruptedException{
205205
if( !isclosed.compareAndSet( false, true ) ){// this also makes sure that no further connections will be added to this.connections
206206
return;
207207
}
@@ -223,21 +223,14 @@ public void stop( int timeout ) throws IOException , InterruptedException{
223223

224224
}
225225
if( selectorthread != Thread.currentThread() ){
226-
selectorthread.interrupt();
226+
if( socketsToClose.size() > 0 )
227+
selectorthread.join( timeout );// isclosed will tell the selectorthread to go down after the last connection was closed
228+
selectorthread.interrupt();// in case the selectorthread did not terminate in time we send the interrupt
227229
selectorthread.join();
228230
}
229231
}
230-
if( decoders != null ){
231-
for( WebSocketWorkerw : decoders ){
232-
w.interrupt();
233-
}
234-
}
235-
if( server != null ){
236-
server.close();
237-
}
238232
}
239233
}
240-
241234
publicvoidstop() throwsIOException , InterruptedException{
242235
stop( 0 );
243236
}
@@ -397,6 +390,19 @@ public void run(){
397390
} catch ( RuntimeExceptione ){
398391
// should hopefully never occur
399392
handleFatal( null, e );
393+
} finally{
394+
if( decoders != null ){
395+
for( WebSocketWorkerw : decoders ){
396+
w.interrupt();
397+
}
398+
}
399+
if( server != null ){
400+
try{
401+
server.close();
402+
} catch ( IOExceptione ){
403+
onError( null, e );
404+
}
405+
}
400406
}
401407
}
402408
protectedvoidallocateBuffers( WebSocketc ) throwsInterruptedException{
@@ -528,19 +534,24 @@ public final void onWebsocketClose( WebSocket conn, int code, String reason, boo
528534
* Depending on the type on the connection, modifications of that collection may have to be synchronized.
529535
**/
530536
protectedbooleanremoveConnection( WebSocketws ){
537+
booleanremoved;
531538
synchronized ( connections ){
532-
returnthis.connections.remove( ws );
539+
removed = this.connections.remove( ws );
540+
assert ( removed );
533541
}
542+
if( isclosed.get() && connections.size() == 0 ){
543+
selectorthread.interrupt();
544+
}
545+
returnremoved;
534546
}
535-
536547
@Override
537548
publicServerHandshakeBuilderonWebsocketHandshakeReceivedAsServer( WebSocketconn, Draftdraft, ClientHandshakerequest ) throwsInvalidDataException{
538549
returnsuper.onWebsocketHandshakeReceivedAsServer( conn, draft, request );
539550
}
540551

541552
/** @see #removeConnection(WebSocket) */
542553
protectedbooleanaddConnection( WebSocketws ){
543-
if( isclosed.get() ){
554+
if( !isclosed.get() ){
544555
synchronized ( connections ){
545556
booleansucc = this.connections.add( ws );
546557
assert ( succ );

0 commit comments

Comments
(0)