33import org .ldk .structs .*;
44
55import java .io .IOException ;
6+ import java .util .LinkedList ;
67import java .net .SocketAddress ;
78import java .net .StandardSocketOptions ;
89import java .nio .Buffer ;
@@ -239,6 +240,11 @@ public void disconnect(byte[] their_node_id) {
239240 this .peer_manager .disconnect_by_node_id (their_node_id , false );
240241 }
241242
243+ /**
244+ * Before shutdown, we have to ensure all of our listening sockets are closed manually, as they appear
245+ * to otherwise remain open and lying around on OSX (though no other platform).
246+ */
247+ private LinkedList <ServerSocketChannel > listening_sockets = new LinkedList ();
242248 /**
243249 * Binds a listening socket to the given address, accepting incoming connections and handling them on the background
244250 * thread.
@@ -248,9 +254,13 @@ public void disconnect(byte[] their_node_id) {
248254 */
249255 public void bind_listener (SocketAddress socket_address ) throws IOException {
250256 ServerSocketChannel listen_channel = ServerSocketChannel .open ();
257+ listen_channel .setOption (StandardSocketOptions .SO_REUSEADDR , true );
251258 listen_channel .bind (socket_address );
252259 listen_channel .configureBlocking (false );
253260 do_selector_action (() -> listen_channel .register (this .selector , SelectionKey .OP_ACCEPT ));
261+ synchronized (listening_sockets ) {
262+ listening_sockets .add (listen_channel );
263+ }
254264 }
255265
256266 /**
@@ -263,6 +273,14 @@ public void interrupt() {
263273 try {
264274 io_thread .join ();
265275 } catch (InterruptedException ignored ) { }
276+ synchronized (listening_sockets ) {
277+ try {
278+ selector .close ();
279+ for (ServerSocketChannel chan : listening_sockets ) {
280+ chan .close ();
281+ }
282+ } catch (IOException ignored ) {}
283+ }
266284 }
267285
268286 /**
0 commit comments