2

Background:

This app is a simple Wifi manager, collecting/scanning and displaying results in a list view. Since this scan scans on a interval, I have created a thread and set a Thread.sleep(interval) between scans, so after processing is done, it sleeps for X milliseconds.

I have made a few "changes"/updates to my code, now my app goes into a ANR state with an debugger message "Signal Catcher"]: reacting to signal 3

Full Error:

07-01 10:14:16.772 10027-10034/com.cynetstudios.wifimanager I/art: Thread[2,tid=10034,WaitingInMainSignalCatcherLoop,Thread*=0xa9007000,peer=0x12d1a0a0,"Signal Catcher"]: reacting to signal 3
07-01 10:14:17.101 10027-10034/com.cynetstudios.wifimanager I/art: Wrote stack traces to '/data/anr/traces.txt'

Problem:

Before Permissions added:

In the onCreate() of main, I had my code to initiate my scan loop and start outputting data, this worked and was outputting data as expected.

Thread Code:

    t = new Thread(new Runnable() {
        public void run() {
            while (!bStopThread) {
                ThreadCounter++;

                if (bSafe) {
                    initWiFiArrays(); //Scans and inserts data into lists
                    CreateSetAdapter(); //Converts lists into adapter, and sets adapter to ExpandableListView
                    threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
                    writeResultsToFile(); //Write results to file
                } else
                    stopScan();

                try {
                    Thread.sleep(scanInterval);
                } catch (Exception x) {
                    x.printStackTrace();
                }
            }
        }
    });
    t.start();

After Permissions added:

After doing some research, I discovered that I should remove this Initiate scan method from onCreate since it blocks any thread calls, I added it to onStart and added a method RunOnUITHD(Runnable r) which will only access UI to update with essential code.

New Thread Code:

     t = new Thread(new Runnable() {
        public void run() {
            while (!bStopThread) {
                ThreadCounter++;

                if (bSafe) {
                    initWiFiArrays();
                    CreateSetAdapter();
                    RunOnUITHD(new Runnable() {
                        @Override
                        public void run() {
                            threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
                        }
                    });
                    writeResultsToFile();
                } else
                    stopScan();

                try {
                    Thread.sleep(scanInterval);
                } catch (Exception x) {
                    x.printStackTrace();
                }
            }
        }
    });
    t.start();

Handler is defined by : handler = new Handler(context.getMainLooper());

RunOnUITHD

private void RunOnUITHD(Runnable runnable) {
    handler.post(runnable);
}

I am still getting ANR (latest ANR Traces) and I am out of idea's, I have no idea what I am doing wrong.

UPDATE:

I logged every part of the main thread code, it is running as expected, looping and sleeping, but UI is not updating...

Adding Logging code to the new Runnable() I notice the following:

adding a breakpoint to ThreadCounter of e.g. ThreadCounter==11 should result in 10 "Updaing Thread..." and "Finished update..." loops as seen from code below.

RunOnUITHD(new Runnable() {
    @Override
    public void run() {
        logm("POST HANDLER: updating Thread Refresh Text");
        threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
        logm("POST HANDLER: Finished update Thread Refresh Text");
    }
});

Instead I only note 4 loops that are shown in log.

Running further tests, ThreadCounter==3, loops logged = 1, allfurther tests results in 1 logged loop of Updating setText.

Since this thread is initiated via a custom method of checkPermissions() in my @Override onStart(), I show a toast message, followed by the checkPermissions

@Override
protected void onStart() {
    super.onStart();
    Toast.makeText(main.this, "Starting Service", Toast.LENGTH_SHORT).show();
    logm("checking permissions in 'onStart'");
    checkPermissions();
}

thoughout these tests, the Toast Message shows (does not disappear) and the setText updates on 1 loop, meaning the threadRefresh TextView contains the following text : "# Refreshed Times : 1"

Cœur
  • 37,241
  • 25
  • 195
  • 267
CybeX
  • 2,060
  • 3
  • 48
  • 115

1 Answers1

1

Turns out I did not have a deadlock, it was due to a poor choice in Intents.

Cause:

What I used was an Intent. This created a service which created a PendingIntent (for the click on notifcation to reopen app), this locked my UI thread. SO nothing in my code above affect/caused the problem!

How I solved this:

Use logs. Not Custom defined logs, just simple Log.i()

I logged each part of my code:

  1. Starting off at high level, and working down to a possible cause.

  2. If that doesn't work/produce results, see if you have any other classes, in my case a ServiceClass, log that.

This is where I found my code did not execute further, so back tracing to the calling code, I discovered that I used an Intent which waits for the intent to finish before moving on, thus causing my code to hang.

Solution:

should have used is one of 2 types of Intents meant for services.

These are frequently asked and well documented objects. There are many questions on StackOverflow regarding the difference between these 2 intent types, here and here are 2 highly ranked questions, and a little UI and service Question

I will be using a IntentService.

Hope this helps!

Community
  • 1
  • 1
CybeX
  • 2,060
  • 3
  • 48
  • 115