I have created a Server with ServerSocket and any connection made is put into a List of Connection
. The list is synchronized (Collections.synchronizedList(new ArrayList<Connection>())
), and I access it properly such as:
synchronized(getConnections()) {
Iterator<Connection> it = getConnections().iterator();
while(it.hasNext()) {
try {
if(!it.next().keepAlive()) {
it.remove();
}
}catch(Exception error) {
ErrorLogger.error(error);
}
}
}
BUT it locks up somewhere at random times. Once it locks, it remains locked forever.
I have created a logging system which logs a message before and after every synchronized block used for this list. (COMPLETE means it went through the synchronized block). Pastebin of the logs with descriptions.
Here is my code for the ADDED
part seen in the logs:
DebugFile.write("ADDED connection");
//This is used to dump empty connections
synchronized(getConnections()) {//Synchronized
getConnections().add(mini);//Adding to List
Iterator<Connection> it = getConnections().iterator();
while(it.hasNext()) {
Connection con = it.next();
if(con.getSocket() == null || !con.getSocket().isConnected() ||
(con.getBungeeServer().equals("Unknown") && System.currentTimeMillis() > con.getCreateTime()+30000)){
System.out.println("[MoltresBungee] Connection disconnecting because they have not identified within 30 seconds.");
con.stop(false);
it.remove();//Removes expired sessions
}
}
Bungee.instance.getLogger().info("MoltresBungee - Active connections: " + getConnections().size());
}
DebugFile.write("ADDED connection - COMPLETE");//Logs complete
Here is code for REMOVE ALL
:
DebugFile.write("REMOVE ALL : " + name);
synchronized(getConnections()) {
Iterator<Connection> it = getConnections().iterator();
while(it.hasNext()) {
Connection con = it.next();
if(con == null || con.getSocket() == null || con.getSocket().isClosed() || con.getBungeeServer().equals(name)){
DebugFile.write("REMOVE ALL : " + name + " removing: " + con.getBungeeServer());
if(con != null && con.getSocket() != null) {
try{
con.getSocket().close();
}catch(Exception e){ErrorLogger.error(e);}
}
it.remove();
}
}
}
DebugFile.write("REMOVE ALL : " + name + " - COMPLETE");
The adding code is suppose to add a connection to this list then remove any items in this list which have lost connection or never completed the handshake.
The remove all code is suppose to remove anything from the list that has the same name or has closed already.
I have about ten more places I used the synchronized(getConnections())
like what is above.
If needed, here is getConnections()
method:
public synchronized List<Connection> getConnections(){
return connections;
}
Why is this locking, and how do I fix it?
EDIT: Also, clients attempting to connect retry over and over until connected, and it seems that all the previous tries are still there when the server turns on. This is when the list locks as well.