powered by Jive Software

Potential Timing and synchronization issue in XMPPConnection

I received the following stacktrace while attempting to login:

at org.jivesoftware.smack.SASLAuthentication.send(SASLAuthentication.java:545)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:130)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:92)
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java: 320)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:423)

at …Custom code which calls XMPPConnection.login()…

544 public void send(String stanza) throws IOException {
545 connection.writer.write(stanza);
546 connection.writer.flush();
547 }

At line 545, XMPPConnection#writer is null, since connection is only set once in the constructor. XMPPConnection#writer can be NULL due to a call to XMPPConnection#shutdown. I think it is possible for different threads to call login() and shutdown() nearly simultaneously, and step on each other, because the code in login() and shutdown() are guarded by different locks. login() is guarded by the lock on the entire XMPPConnection object, and the code in shutdown() is guarded by XMPPConnection#connectLock. Thus it is possible for shutdown() to nullify the connection’s writer during login().

* Lock to guard threads from calling {@link #disconnect()} or {@link #shutdown(Presence)}
* while {@link #connect()} is being called.
* The problem is that creation listeners install {@link PacketListener}
* on a connection in the thread that calls {@link #connect()} while
* the thread of {@link #packetReader} might close the connection due
* to an error.
* This causes an {@link IllegalStateException} to be thrown for these
* listeners.
private final Object connectLock = new Object();

********* Maybe login() should hold the connectLock instead of locking on the XMPPConnection object.