Skip to content

Commit f4f2443

Browse files
committed
Attempt at fixing connection handler synchronization mess.
... and in turn, uncovering a few more problems that we'll have to deal with down the line. This should be okay as a quick fix for version 1.1.0, though.
1 parent 52fa42a commit f4f2443

1 file changed

Lines changed: 56 additions & 14 deletions

File tree

src/main/java/com/github/theholywaffle/teamspeak3/TS3Query.java

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ public int getMs() {
6464
}
6565

6666
private final ConnectionHandler connectionHandler;
67-
private final EventManager eventManager = new EventManager(this);
68-
private final ExecutorService userThreadPool = Executors.newCachedThreadPool();
67+
private final EventManager eventManager;
68+
private final ExecutorService userThreadPool;
6969
private final FileTransferHelper fileTransferHelper;
7070
private final TS3Api api;
7171
private final TS3ApiAsync asyncApi;
@@ -93,34 +93,55 @@ public TS3Query() {
9393
*/
9494
public TS3Query(TS3Config config) {
9595
this.config = config;
96+
this.eventManager = new EventManager(this);
97+
this.userThreadPool = Executors.newCachedThreadPool();
9698
this.fileTransferHelper = new FileTransferHelper(config.getHost());
9799
this.connectionHandler = config.getReconnectStrategy().create(config.getConnectionHandler());
98100

99101
this.asyncApi = new TS3ApiAsync(this);
100102
this.api = new TS3Api(asyncApi);
101103
}
102104

103-
// PUBLIC
105+
/*
106+
* Copy constructor only used for ReconnectQuery
107+
*/
108+
private TS3Query(TS3Query query) {
109+
this.config = query.config;
110+
this.eventManager = query.eventManager;
111+
this.userThreadPool = query.userThreadPool;
112+
this.fileTransferHelper = query.fileTransferHelper;
113+
this.connectionHandler = null;
104114

105-
public synchronized void connect() {
106-
if (userThreadPool.isShutdown()) {
107-
throw new IllegalStateException("The query has already been shut down");
108-
}
115+
this.asyncApi = new TS3ApiAsync(this);
116+
this.api = new TS3Api(asyncApi);
117+
}
118+
119+
// PUBLIC
109120

110-
QueryIO oldIO = io;
111-
if (oldIO != null) {
112-
oldIO.disconnect();
121+
public void connect() {
122+
synchronized (this) {
123+
if (userThreadPool.isShutdown()) {
124+
throw new IllegalStateException("The query has already been shut down");
125+
}
113126
}
114127

115-
io = new QueryIO(this, config);
116-
connected.set(true);
128+
QueryIO newIO = new QueryIO(this, config);
117129

118130
try {
119-
connectionHandler.onConnect(this);
131+
connectionHandler.onConnect(new ReconnectQuery(this, newIO));
120132
} catch (Exception e) {
121133
log.error("ConnectionHandler threw exception in connect handler", e);
122134
}
123-
io.continueFrom(oldIO);
135+
136+
synchronized (this) {
137+
QueryIO oldIO = io;
138+
io = newIO;
139+
if (oldIO != null) {
140+
oldIO.disconnect();
141+
newIO.continueFrom(io);
142+
}
143+
connected.set(true);
144+
}
124145
}
125146

126147
/**
@@ -247,4 +268,25 @@ private synchronized void handleDisconnect() {
247268
}
248269
}
249270
}
271+
272+
private static class ReconnectQuery extends TS3Query {
273+
274+
private final TS3Query parent;
275+
276+
private ReconnectQuery(TS3Query query, QueryIO io) {
277+
super(query);
278+
super.io = io;
279+
this.parent = query;
280+
}
281+
282+
@Override
283+
public void connect() {
284+
throw new UnsupportedOperationException("Can't call connect from onConnect");
285+
}
286+
287+
@Override
288+
public void exit() {
289+
parent.exit();
290+
}
291+
}
250292
}

0 commit comments

Comments
 (0)