Fixes to keep the kernel adapter threads from hanging.

Closing the underlying kernel didn't wake up any readers
and so the read() operation in the adapter was never returning.
KernelAdapter.close() was modified to call join() after closing
the underlying kernel so that the method won't complete until
all of the threads are done.
Then the kernels were modified to wakeup the readers (and this
is now standardized in a base class method) so that they don't
hang forever.
experimental
Paul Speed 9 years ago
parent 84a38d1363
commit ac672df63a
  1. 4
      jme3-networking/src/main/java/com/jme3/network/base/KernelAdapter.java
  2. 12
      jme3-networking/src/main/java/com/jme3/network/kernel/AbstractKernel.java
  3. 13
      jme3-networking/src/main/java/com/jme3/network/kernel/tcp/SelectorKernel.java
  4. 13
      jme3-networking/src/main/java/com/jme3/network/kernel/udp/UdpKernel.java

@ -112,6 +112,8 @@ public class KernelAdapter extends Thread
// Kill the kernel // Kill the kernel
kernel.terminate(); kernel.terminate();
join();
} }
protected void reportError( Endpoint p, Object context, Exception e ) protected void reportError( Endpoint p, Object context, Exception e )
@ -120,6 +122,8 @@ public class KernelAdapter extends Thread
// retrieve them. For now we'll just log it. FIXME // retrieve them. For now we'll just log it. FIXME
log.log( Level.SEVERE, "Unhandled error, endpoint:" + p + ", context:" + context, e ); log.log( Level.SEVERE, "Unhandled error, endpoint:" + p + ", context:" + context, e );
//if( p.isConnected() )
System.out.println("Is p connected:" + p.isConnected());
// In lieu of other options, at least close the endpoint // In lieu of other options, at least close the endpoint
p.close(); p.close();
} }

@ -76,6 +76,18 @@ public abstract class AbstractKernel implements Kernel
log.log( Level.SEVERE, "Unhanddled kernel error", e ); log.log( Level.SEVERE, "Unhanddled kernel error", e );
} }
protected void wakeupReader() {
// If there are no pending messages then add one so that the
// kernel-user knows to wake up if it is only listening for
// envelopes.
if( !hasEnvelopes() ) {
// Note: this is not really a race condition. At worst, our
// event has already been handled by now and it does no harm
// to check again.
addEnvelope( EVENTS_PENDING );
}
}
protected long nextEndpointId() protected long nextEndpointId()
{ {
return nextId.getAndIncrement(); return nextId.getAndIncrement();

@ -106,6 +106,9 @@ public class SelectorKernel extends AbstractKernel
try { try {
thread.close(); thread.close();
thread = null; thread = null;
// Need to let any caller waiting for a read() wakeup
wakeupReader();
} catch( IOException e ) { } catch( IOException e ) {
throw new KernelException( "Error closing host connection:" + address, e ); throw new KernelException( "Error closing host connection:" + address, e );
} }
@ -164,15 +167,7 @@ public class SelectorKernel extends AbstractKernel
// Enqueue an endpoint event for the listeners // Enqueue an endpoint event for the listeners
addEvent( EndpointEvent.createRemove( this, p ) ); addEvent( EndpointEvent.createRemove( this, p ) );
// If there are no pending messages then add one so that the wakeupReader();
// kernel-user knows to wake up if it is only listening for
// envelopes.
if( !hasEnvelopes() ) {
// Note: this is not really a race condition. At worst, our
// event has already been handled by now and it does no harm
// to check again.
addEnvelope( EVENTS_PENDING );
}
} }
/** /**

@ -110,6 +110,9 @@ public class UdpKernel extends AbstractKernel
thread.close(); thread.close();
writer.shutdown(); writer.shutdown();
thread = null; thread = null;
// Need to let any caller waiting for a read() wakeup
wakeupReader();
} catch( IOException e ) { } catch( IOException e ) {
throw new KernelException( "Error closing host connection:" + address, e ); throw new KernelException( "Error closing host connection:" + address, e );
} }
@ -170,15 +173,7 @@ public class UdpKernel extends AbstractKernel
addEvent( EndpointEvent.createRemove( this, p ) ); addEvent( EndpointEvent.createRemove( this, p ) );
// If there are no pending messages then add one so that the wakeupReader();
// kernel-user knows to wake up if it is only listening for
// envelopes.
if( !hasEnvelopes() ) {
// Note: this is not really a race condition. At worst, our
// event has already been handled by now and it does no harm
// to check again.
addEnvelope( EVENTS_PENDING );
}
} }
protected void newData( DatagramPacket packet ) protected void newData( DatagramPacket packet )

Loading…
Cancel
Save