fusesource / mqtt-client

A Java MQTT Client
http://mqtt-client.fusesource.org/
Apache License 2.0
1.27k stars 369 forks source link

Mqtt-client doesn't work on Android 3.x #5

Open a-thomas opened 12 years ago

a-thomas commented 12 years ago

I develop a Mqtt-client on Android for 3.x tablet version.

My client works well with Android 2.x version but not with Android 3.x. On Android 3.x, my request is never sent to my Broker (I use Mosquitto). I debugged my project and I think I found out the problem's location:

The application blocks in the pickThreadQueue method of the NioDispatchSource class at the followed line:

int s = threads[i].getNioManager().getSelector().keys().size();

The only difference between Android 3.x and Android 2.x is the Selector Implementation. org.apache.harmony.nio.internal.SelectorImpl on 2.x java.nio.SelectorImplon 3.x

So, it works with apache harmony Selector implementation and not with java.nio... Have you an idea why it doesn't work ? Thanks for your answers.

baobeimm commented 12 years ago

Were you able to solve this problem? We have the same issue now.

chirino commented 12 years ago

Hi I've never working on android before. Do you guys have any tips on how I can setup a testing environment that I can #1 reproduce the issue, and #2 attach a debugger against?

vijayraghunathan commented 12 years ago

FYI I think the problem is that in the apache harmony version, calling 'keys' returns an UnmodifiableSet[1](which I believe is threadsafe) and the java.nio.Selector documentation[2] says that keys is not threadsafe. Is this in the hawtdispatch code? I believe wrapping all concurrent thread usage of the keys object would a ConcurrentSet might fix the problem.

If you can reproduce the deadlock on your phone, you should be able to see the other thread that is holding the lock using DDMS (ddms is a tool available in the android-sdk installation, attach your phone, start ddms, select your phone and app, then click threads).

[1]http://www.docjar.com/html/api/org/apache/harmony/nio/internal/SelectorImpl.java.html line 83 [2]http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/channels/Selector.html#keys()

vijayraghunathan commented 12 years ago

I believe wrapping all concurrent thread usage of the keys object would a ConcurrentSet might fix the problem.

vijayraghunathan commented 12 years ago

Also I have seen this issue on the new Nexus phones running ICS (Android 4.0), the Galaxy Tablet running Android 3.0, but not on a Nexus S (older generation) running ICS. So to repro, i believe it is best to use the new Nexus or the Galaxy Tab (or emulator)

vijayraghunathan commented 12 years ago

screenshot of deadlock

http://imgur.com/0x08Q http://imgur.com/ftEcl

vijayraghunathan commented 12 years ago

I believe the problem is in this code.

We query the selector to determine the # of keys, but we have another thread accessing the same selector calling park. According to http://rox-xmlrpc.sourceforge.net/niotut/ (and the JDK documentation) these objects aren't threadsafe.

On an android device, we're almost certainly going to be dealing w/ just one thread so we can probably just shortcircuit this code to pick the first (or a random) worker thread.

      // otherwise.. pick the thread queue with the fewest registered selection
        // keys.
        if( selectorQueue.getQueueType()!=THREAD_QUEUE ) {

            WorkerThread[] threads = dispatcher.DEFAULT_QUEUE.workers.getThreads();
            WorkerThread min = threads[0];
            int minSize = min.getNioManager().getSelector().keys().size();
            for( int i=1; i < threads.length; i++) {
                int s = threads[i].getNioManager().getSelector().keys().size();
                if( s < minSize ) {
                    minSize = s;
                    min = threads[i];
                }
            }
            selectorQueue = min.getDispatchQueue();
hooby3dfx commented 10 years ago

Would this occur when calling connect() on a blocking connection? This seems to be working fine in Android 4.1+ but I discovered that hanging in ICS. Was this resolved?