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-
public void stop( int timeout ) throws IOException , InterruptedException {
204+
public void stop( int timeout ) throws InterruptedException {
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( WebSocketWorker w : decoders ) {
232-
w.interrupt();
233-
}
234-
}
235-
if( server != null ) {
236-
server.close();
237-
}
238232
}
239233
}
240-
241234
public void stop() throws IOException , InterruptedException {
242235
stop( 0 );
243236
}
@@ -397,6 +390,19 @@ public void run() {
397390
} catch ( RuntimeException e ) {
398391
// should hopefully never occur
399392
handleFatal( null, e );
393+
} finally {
394+
if( decoders != null ) {
395+
for( WebSocketWorker w : decoders ) {
396+
w.interrupt();
397+
}
398+
}
399+
if( server != null ) {
400+
try {
401+
server.close();
402+
} catch ( IOException e ) {
403+
onError( null, e );
404+
}
405+
}
400406
}
401407
}
402408
protected void allocateBuffers( WebSocket c ) throws InterruptedException {
@@ -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
protected boolean removeConnection( WebSocket ws ) {
537+
boolean removed;
531538
synchronized ( connections ) {
532-
return this.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+
return removed;
534546
}
535-
536547
@Override
537548
public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException {
538549
return super.onWebsocketHandshakeReceivedAsServer( conn, draft, request );
539550
}
540551

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

0 commit comments

Comments
 (0)