Listener.connectionClosedOnError can be called twice in a row:
In PacketWriter.java in void writePackets(Thread thisThread)
catch (IOException ioe){
if (!done) {
done = true;
connection.packetReader.notifyConnectionError(ioe);
}
}
in PacketReader.java in void parsePackets(Thread thread)
catch (Exception e) {
if (!done) {
// Close the connection and notify connection listeners of the
// error.
notifyConnectionError(e);
}
}
The done flag is not shared between this two classes so the listener can be triggered twice:
void notifyConnectionError(Exception e) {
done = true;
// Closes the connection temporary. A reconnection is possible
connection.shutdown(new Presence(Presence.Type.unavailable));
// Print the stack trace to help catch the problem
e.printStackTrace();
// Notify connection listeners of the error.
for (ConnectionListener listener : connectionListeners) {
try {
listener.connectionClosedOnError(e);
}
catch (Exception e2) {
// Cath and print any exception so we can recover
// from a faulty listener
e2.printStackTrace();
}
}
}
This happen to me while I use Smack in an Android application running on the T-Mobile G1 phone when I lose the network. I don’t think it’s intented to call twice the listener function, I never reproduced that in a desktop environment.
I proposed the following replacement code for notifyConnectionError:
+ synchronized void notifyConnectionError(Exception e) {
+ if (!done) {
+ done = true;
+ // Closes the connection temporary. A reconnection is possible
+ connection.shutdown(new Presence(Presence.Type.unavailable));
+ // Print the stack trace to help catch the problem
+ e.printStackTrace();
+ // Notify connection listeners of the error.
+ for (ConnectionListener listener : connectionListeners) {
+ try {
+ listener.connectionClosedOnError(e);
+ }
+ catch (Exception e2) {
+ // Cath and print any exception so we can recover
+ // from a faulty listener
+ e2.printStackTrace();
+ }
+ }
The full patch is attached in this thread.
PacketReader.java.patch (1930 Bytes)