[concurrency-interest] Impossible Exception?

Sam Berlin sberlin at gmail.com
Fri Jan 11 22:50:30 EST 2008


We have a simple class that's intended to lazily load a singleton,
throwing an exception if it detects a circular construction
dependency.  However, occasionally a bug report is sent with the
exception being thrown, but the stack trace shows no sign of circular
dependency.  This is the class:

---
public abstract class AbstractLazySingletonProvider<T> implements Provider<T> {

    /** The backing object. */
    private T obj;

    /** Whether or not construction has already started. */
    private boolean constructing;

    /** Retrieves the reference, creating it if necessary. */
    public synchronized T get() {
        if(obj == null) {
            if(constructing)
                throw new IllegalStateException("constructing again!");
            constructing = true;
            obj = createObject();
        }
        return obj;
    }

    /** Creates the object this reference will use. */
    protected abstract T createObject();

}
---

It protects against concurrent access by get() being synchronized, so
another thread attempting to retrieve should block until the first one
is done.  (Yes, this could potentially create deadlocks in
multi-threaded circular access, but fortunately that isn't happening.)

This is an example stack trace we're seeing:
--
java.lang.IllegalStateException: constructing again!
    at org.limewire.concurrent.AbstractLazySingletonProvider.get(AbstractLazySingletonProvider.java:28)
    at org.limewire.nio.ssl.SSLUtils.getTLSContext(SSLUtils.java:56)
    at org.limewire.nio.ssl.TLSNIOSocket.initOutgoingSocket(TLSNIOSocket.java:85)
    at org.limewire.nio.NIOSocket.<init>(NIOSocket.java:57)
    at org.limewire.nio.ssl.TLSNIOSocket.<init>(TLSNIOSocket.java:45)
    at org.limewire.nio.ssl.TLSSocketFactory.createSocket(TLSSocketFactory.java:17)
    at org.limewire.nio.ssl.TLSSocketFactory.createSocket(TLSSocketFactory.java:13)
    at org.limewire.net.LimitedSocketController.connectPlain(LimitedSocketController.java:75)
    at org.limewire.net.SimpleSocketController.connect(SimpleSocketController.java:46)
    at org.limewire.net.SocketsManagerImpl.connect(SocketsManagerImpl.java:48)
    at com.limegroup.gnutella.connection.GnutellaConnection.initialize(GnutellaConnection.java:485)
    at com.limegroup.gnutella.connection.GnutellaConnection.initialize(GnutellaConnection.java:453)
    at com.limegroup.gnutella.ConnectionManagerImpl.initializeFetchedConnection(ConnectionManagerImpl.java:1893)
    at com.limegroup.gnutella.ConnectionManagerImpl.access$1500(ConnectionManagerImpl.java:104)
    at com.limegroup.gnutella.ConnectionManagerImpl$ConnectionFetcher.handleEndpoint(ConnectionManagerImpl.java:2340)
    at com.limegroup.gnutella.HostCatcher.getAnEndpoint(HostCatcher.java:1039)
    at com.limegroup.gnutella.ConnectionManagerImpl$ConnectionFetcher.connect(ConnectionManagerImpl.java:2285)
    at com.limegroup.gnutella.ConnectionManagerImpl.adjustConnectionFetchers(ConnectionManagerImpl.java:1821)
    at com.limegroup.gnutella.ConnectionManagerImpl.cleanupBrokenFetchedConnection(ConnectionManagerImpl.java:1915)
    at com.limegroup.gnutella.ConnectionManagerImpl.access$1900(ConnectionManagerImpl.java:104)
    at com.limegroup.gnutella.ConnectionManagerImpl$ConnectionFetcher.shutdown(ConnectionManagerImpl.java:2360)
    at com.limegroup.gnutella.connection.GnutellaConnection$AsyncHandshakeConnecter.shutdown(GnutellaConnection.java:1257)
    at org.limewire.net.LimitedSocketController$DelegateConnector.shutdown(LimitedSocketController.java:237)
    at org.limewire.nio.AbstractNBSocket.shutdownObservers(AbstractNBSocket.java:535)
    at org.limewire.nio.AbstractNBSocket.shutdown(AbstractNBSocket.java:515)
    at org.limewire.nio.NIODispatcher.cancel(NIODispatcher.java:403)
    at org.limewire.nio.NIODispatcher.access$1000(NIODispatcher.java:93)
    at org.limewire.nio.NIODispatcher$Attachment.notifyTimeout(NIODispatcher.java:989)
    at org.limewire.nio.timeout.TimeoutController.processTimeouts(TimeoutController.java:56)
    at org.limewire.nio.NIODispatcher.process(NIODispatcher.java:656)
    at org.limewire.nio.NIODispatcher.run(NIODispatcher.java:867)
    at java.lang.Thread.run(Unknown Source)
--

Can anyone explain how the exception could possibly be thrown?  It's
either something simple that I'm overlooking, or impossible
behavior... but at this point, I can't tell.

Thanks much,
 Sam


More information about the Concurrency-interest mailing list