From 157458af69304d6737bbfc09e4bb1203e5a32a1e Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Tue, 6 Jul 2010 14:48:34 +0000 Subject: [PATCH] Fix a deadlock occurring for jabber accounts, which during login fire connection failed. --- resources/languages/resources.properties | 2 +- .../ProtocolProviderServiceJabberImpl.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index e5e843459..06b9aaff2 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -943,4 +943,4 @@ plugin.globalproxy.PROTOCOL_SUPPORT= \ # plugin reconnect plugin.reconnectplugin.CONNECTION_FAILED_MSG=Connection failed for the following account:\nUser name: {0}, Server name: {1}.\nPlease check your settings or contact your network administrator for more information. -plugin.reconnectplugin.NETWORK_DOWN=Network is down! +plugin.reconnectplugin.NETWORK_DOWN=Network connectivity lost! diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 5c42e4d82..478fcfab5 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -169,6 +169,22 @@ public class ProtocolProviderServiceJabberImpl */ private boolean certChecked = false; + /** + * Flag indicating are we currently executing connectAndLogin method. + */ + private boolean inConnectAndLogin = false; + + /** + * Object used to synchronize the flag inConnectAndLogin. + */ + private final Object connectAndLoginLock = new Object(); + + /** + * If an event occurs during login we fire it at the end of the login + * process (at the end of connectAndLogin method). + */ + private RegistrationStateChangeEvent eventDuringLogin = null; + /** * Returns the state of the registration of this protocol provider * @return the RegistrationState that this provider is @@ -293,6 +309,11 @@ private synchronized void connectAndLogin(SecurityAuthority authority, int reasonCode) throws XMPPException, OperationFailedException { + synchronized(connectAndLoginLock) + { + inConnectAndLogin = true; + } + synchronized(initializationLock) { //verify whether a password has already been stored for this account @@ -591,6 +612,30 @@ else if(globalProxyType.equals( OperationFailedException.INVALID_ACCOUNT_PROPERTIES, ex); } } + + synchronized(connectAndLoginLock) + { + // Checks if an error has occured during login, if so we fire + // it here in order to avoid a deadlock which occurs in + // reconnect plugin. The deadlock is cause we fired an event during + // login process and have locked initializationLock and we cannot + // unregister from reconnect, cause unregister method + // also needs this lock. + if(eventDuringLogin != null) + { + fireRegistrationStateChanged( + eventDuringLogin.getOldState(), + eventDuringLogin.getNewState(), + eventDuringLogin.getReasonCode(), + eventDuringLogin.getReason()); + + eventDuringLogin = null; + inConnectAndLogin = false; + return; + } + + inConnectAndLogin = false; + } } /** @@ -1004,6 +1049,23 @@ public void connectionClosedOnError(Exception exception) if(err != null && err.getCode().equals( XMPPError.Condition.conflict.toString())) { + // if we are in the middle of connecting process + // do not fire events, will do it later when the method + // connectAndLogin finishes its work + synchronized(connectAndLoginLock) + { + if(inConnectAndLogin) + { + eventDuringLogin = new RegistrationStateChangeEvent( + ProtocolProviderServiceJabberImpl.this, + getRegistrationState(), + RegistrationState.CONNECTION_FAILED, + RegistrationStateChangeEvent.REASON_MULTIPLE_LOGINS, + "Connecting multiple times with the same resource"); + return; + } + } + fireRegistrationStateChanged(getRegistrationState(), RegistrationState.CONNECTION_FAILED, RegistrationStateChangeEvent.REASON_MULTIPLE_LOGINS, @@ -1017,6 +1079,23 @@ else if(exception instanceof SSLHandshakeException && return; } + // if we are in the middle of connecting process + // do not fire events, will do it later when the method + // connectAndLogin finishes its work + synchronized(connectAndLoginLock) + { + if(inConnectAndLogin) + { + eventDuringLogin = new RegistrationStateChangeEvent( + ProtocolProviderServiceJabberImpl.this, + getRegistrationState(), + RegistrationState.CONNECTION_FAILED, + RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, + exception.getMessage()); + return; + } + } + fireRegistrationStateChanged(getRegistrationState(), RegistrationState.CONNECTION_FAILED, RegistrationStateChangeEvent.REASON_NOT_SPECIFIED,