Gottox / socket.io-java-client

Socket.IO Client Implementation in Java
MIT License
950 stars 387 forks source link

SocketIO.connect throws ConcurrentModificationException #77

Open wuxudong opened 10 years ago

wuxudong commented 10 years ago

Following code throws java.util.ConcurrentModificationException at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953) at java.util.LinkedList$ListItr.next(LinkedList.java:886) at io.socket.IOConnection.register(IOConnection.java:239) at io.socket.SocketIO.setAndConnect(SocketIO.java:220) at io.socket.SocketIO.connect(SocketIO.java:183) at SocketIOTest$1.run(SocketIOTest.java:23)

import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONObject;
import org.junit.Test;

/**
 * User: xudong
 * Date: 1/10/14
 * Time: 11:52 PM
 */
public class SocketIOTest {
    @Test
    public void test() {
        for (int i = 0; i < 500; i++) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        SocketIO socket = new SocketIO("http://127.0.0.1:9093");

                        socket.connect(new IOCallback() {

                            @Override
                            public void onDisconnect() {
                                System.out.println("disconnected");
                            }

                            @Override
                            public void onConnect() {
                                System.out.println("connected");
                            }

                            @Override
                            public void onMessage(String data, IOAcknowledge ack) {
                            }

                            @Override
                            public void onMessage(JSONObject json, IOAcknowledge ack) {
                            }

                            @Override
                            public void on(String event, IOAcknowledge ack, Object... args) {
                            }

                            @Override
                            public void onError(SocketIOException socketIOException) {
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }

        try {
            Thread.sleep(10000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
bossonchan commented 10 years ago

Same problem.. Has anyone figured out how to fix this?

wuxudong commented 10 years ago

There is a simple brute solution. Look at code in io.socket.IOConnection.register(String origin, SocketIO socket)

static public IOConnection register(String origin, SocketIO socket) {
        List<IOConnection> list = connections.get(origin);
        if (list == null) {
            list = new LinkedList<IOConnection>();
            connections.put(origin, list);
        } else {
            synchronized (list) {
                for (IOConnection connection : list) {
                    if (connection.register(socket))
                        return connection;
                }
            }
        }

        IOConnection connection = new IOConnection(origin, socket);
        list.add(connection);
        return connection;
    }

one thread is iterating list, and another thread calls list.add(connection), ConcurrentModificationException will be thrown.

Simplest solution is

static public synchronized IOConnection register(String origin, SocketIO socket) {
        List<IOConnection> list = connections.get(origin);
        if (list == null) {
            list = new LinkedList<IOConnection>();
            connections.put(origin, list);
        } else {
                for (IOConnection connection : list) {
                    if (connection.register(socket))
                        return connection;
                }
        }

        IOConnection connection = new IOConnection(origin, socket);
        list.add(connection);
        return connection;
    }

After modifying the source code, the previous test passed. Enjoy it.

bossonchan commented 10 years ago

It works for me. Thanks @wuxudong !