Skip to content

Commit e8209ed

Browse files
committed
Fixed shyiko#230 - calling disconnect() inside onDisconnect() may lead to a deadlock
1 parent c06d2bd commit e8209ed

File tree

1 file changed

+27
-53
lines changed

1 file changed

+27
-53
lines changed

src/main/java/com/github/shyiko/mysql/binlog/BinaryLogClient.java

+27-53
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@
6464
import java.security.cert.X509Certificate;
6565
import java.util.Arrays;
6666
import java.util.Collections;
67-
import java.util.Iterator;
6867
import java.util.LinkedList;
6968
import java.util.List;
7069
import java.util.concurrent.Callable;
70+
import java.util.concurrent.CopyOnWriteArrayList;
7171
import java.util.concurrent.CountDownLatch;
7272
import java.util.concurrent.ExecutorService;
7373
import java.util.concurrent.Executors;
@@ -136,8 +136,8 @@ public X509Certificate[] getAcceptedIssuers() {
136136

137137
private EventDeserializer eventDeserializer = new EventDeserializer();
138138

139-
private final List<EventListener> eventListeners = new LinkedList<EventListener>();
140-
private final List<LifecycleListener> lifecycleListeners = new LinkedList<LifecycleListener>();
139+
private final List<EventListener> eventListeners = new CopyOnWriteArrayList<EventListener>();
140+
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<LifecycleListener>();
141141

142142
private SocketFactory socketFactory;
143143
private SSLSocketFactory sslSocketFactory;
@@ -542,10 +542,8 @@ public void connect() throws IOException {
542542
logger.info("Connected to " + hostname + ":" + port + " at " + position +
543543
" (" + (blocking ? "sid:" + serverId + ", " : "") + "cid:" + connectionId + ")");
544544
}
545-
synchronized (lifecycleListeners) {
546-
for (LifecycleListener lifecycleListener : lifecycleListeners) {
547-
lifecycleListener.onConnect(this);
548-
}
545+
for (LifecycleListener lifecycleListener : lifecycleListeners) {
546+
lifecycleListener.onConnect(this);
549547
}
550548
if (keepAlive && !isKeepAliveThreadRunning()) {
551549
spawnKeepAliveThread();
@@ -560,10 +558,8 @@ public void connect() throws IOException {
560558
} finally {
561559
connectLock.unlock();
562560
if (notifyWhenDisconnected) {
563-
synchronized (lifecycleListeners) {
564-
for (LifecycleListener lifecycleListener : lifecycleListeners) {
565-
lifecycleListener.onDisconnect(this);
566-
}
561+
for (LifecycleListener lifecycleListener : lifecycleListeners) {
562+
lifecycleListener.onDisconnect(this);
567563
}
568564
}
569565
}
@@ -899,10 +895,8 @@ private void listenForEventPackets() throws IOException {
899895
throw e;
900896
}
901897
if (isConnected()) {
902-
synchronized (lifecycleListeners) {
903-
for (LifecycleListener lifecycleListener : lifecycleListeners) {
904-
lifecycleListener.onEventDeserializationFailure(this, e);
905-
}
898+
for (LifecycleListener lifecycleListener : lifecycleListeners) {
899+
lifecycleListener.onEventDeserializationFailure(this, e);
906900
}
907901
}
908902
continue;
@@ -916,10 +910,8 @@ private void listenForEventPackets() throws IOException {
916910
}
917911
} catch (Exception e) {
918912
if (isConnected()) {
919-
synchronized (lifecycleListeners) {
920-
for (LifecycleListener lifecycleListener : lifecycleListeners) {
921-
lifecycleListener.onCommunicationFailure(this, e);
922-
}
913+
for (LifecycleListener lifecycleListener : lifecycleListeners) {
914+
lifecycleListener.onCommunicationFailure(this, e);
923915
}
924916
}
925917
} finally {
@@ -1016,22 +1008,16 @@ public List<EventListener> getEventListeners() {
10161008
* where registered.
10171009
*/
10181010
public void registerEventListener(EventListener eventListener) {
1019-
synchronized (eventListeners) {
1020-
eventListeners.add(eventListener);
1021-
}
1011+
eventListeners.add(eventListener);
10221012
}
10231013

10241014
/**
10251015
* Unregister all event listener of specific type.
10261016
*/
10271017
public void unregisterEventListener(Class<? extends EventListener> listenerClass) {
1028-
synchronized (eventListeners) {
1029-
Iterator<EventListener> iterator = eventListeners.iterator();
1030-
while (iterator.hasNext()) {
1031-
EventListener eventListener = iterator.next();
1032-
if (listenerClass.isInstance(eventListener)) {
1033-
iterator.remove();
1034-
}
1018+
for (EventListener eventListener: eventListeners) {
1019+
if (listenerClass.isInstance(eventListener)) {
1020+
eventListeners.remove(eventListener);
10351021
}
10361022
}
10371023
}
@@ -1040,23 +1026,19 @@ public void unregisterEventListener(Class<? extends EventListener> listenerClass
10401026
* Unregister single event listener.
10411027
*/
10421028
public void unregisterEventListener(EventListener eventListener) {
1043-
synchronized (eventListeners) {
1044-
eventListeners.remove(eventListener);
1045-
}
1029+
eventListeners.remove(eventListener);
10461030
}
10471031

10481032
private void notifyEventListeners(Event event) {
10491033
if (event.getData() instanceof EventDeserializer.EventDataWrapper) {
10501034
event = new Event(event.getHeader(), ((EventDeserializer.EventDataWrapper) event.getData()).getExternal());
10511035
}
1052-
synchronized (eventListeners) {
1053-
for (EventListener eventListener : eventListeners) {
1054-
try {
1055-
eventListener.onEvent(event);
1056-
} catch (Exception e) {
1057-
if (logger.isLoggable(Level.WARNING)) {
1058-
logger.log(Level.WARNING, eventListener + " choked on " + event, e);
1059-
}
1036+
for (EventListener eventListener : eventListeners) {
1037+
try {
1038+
eventListener.onEvent(event);
1039+
} catch (Exception e) {
1040+
if (logger.isLoggable(Level.WARNING)) {
1041+
logger.log(Level.WARNING, eventListener + " choked on " + event, e);
10601042
}
10611043
}
10621044
}
@@ -1074,22 +1056,16 @@ public List<LifecycleListener> getLifecycleListeners() {
10741056
* where registered.
10751057
*/
10761058
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
1077-
synchronized (lifecycleListeners) {
1078-
lifecycleListeners.add(lifecycleListener);
1079-
}
1059+
lifecycleListeners.add(lifecycleListener);
10801060
}
10811061

10821062
/**
10831063
* Unregister all lifecycle listener of specific type.
10841064
*/
10851065
public void unregisterLifecycleListener(Class<? extends LifecycleListener> listenerClass) {
1086-
synchronized (lifecycleListeners) {
1087-
Iterator<LifecycleListener> iterator = lifecycleListeners.iterator();
1088-
while (iterator.hasNext()) {
1089-
LifecycleListener lifecycleListener = iterator.next();
1090-
if (listenerClass.isInstance(lifecycleListener)) {
1091-
iterator.remove();
1092-
}
1066+
for (LifecycleListener lifecycleListener : lifecycleListeners) {
1067+
if (listenerClass.isInstance(lifecycleListener)) {
1068+
lifecycleListeners.remove(lifecycleListener);
10931069
}
10941070
}
10951071
}
@@ -1098,9 +1074,7 @@ public void unregisterLifecycleListener(Class<? extends LifecycleListener> liste
10981074
* Unregister single lifecycle listener.
10991075
*/
11001076
public void unregisterLifecycleListener(LifecycleListener eventListener) {
1101-
synchronized (lifecycleListeners) {
1102-
lifecycleListeners.remove(eventListener);
1103-
}
1077+
lifecycleListeners.remove(eventListener);
11041078
}
11051079

11061080
/**

0 commit comments

Comments
 (0)