Calling pjlib from unknown/external thread. You must " "register external threads with pj_thread_register()

5.9k views Asked by At

I have integrated pjsua2 in my android application. The application crashes when I send an SMS. It doesn't crash every time, it is happening randomly. (once every 10 messages).

MyCode is:

public void sendInstantMessage(String number, String msgBody) {

    String buddy_uri = "<sip:" + number + "@" + mPref.getString(PREF_SIPSERVER, "") + ">";
    Log.e(TAG, "sendInstantMessage ==== "+buddy_uri);

    BuddyConfig bCfg = new BuddyConfig();
    bCfg.setUri(buddy_uri);
    bCfg.setSubscribe(false);

    MyBuddy im = new MyBuddy(bCfg);
    SendInstantMessageParam prm = new SendInstantMessageParam();
    prm.setContent(msgBody);
    prm.setContentType("text/plain; charset=utf-8");

    try {
        im.create(account, bCfg);
        boolean valid1 = im.isValid();
        Log.e(TAG, "valid1 ======= "+valid1);
        im.sendInstantMessage(prm);
    } catch (Exception e) {
        Log.e(TAG, "sendInstantMessage ==== "+e);
        e.printStackTrace();
        return;
    }

}

According to logcat , I have to call pj_thread_register(). But I have got a method libRegisterThread() in endpoint, so I used it like below

MyApp.ep.libRegisterThread("SipApi");

Here is the logcat:

../src/pj/os_core_unix.c:692: pj_thread_this: assertion "!"Calling pjlib from unknown/external thread. You must " "register external threads with pj_thread_register() " "before calling any pjlib functions."" failed
3

There are 3 answers

0
Gangadhar Nimballi On BEST ANSWER

Here is the correct answer.

/**Send message to this number
 * @param String number
 * @param String msgBody*/
public void sendInstantMessage(String number, String msgBody) {
    String sipServer = "aaa.ggg.net";
    String buddy_uri = "<sip:" + number + "@" + sipServer + ">";

    BuddyConfig bCfg = new BuddyConfig();
    bCfg.setUri(buddy_uri);
    bCfg.setSubscribe(false);

    MyBuddy myBuddy = new MyBuddy(bCfg);
    SendInstantMessageParam prm = new SendInstantMessageParam();
    prm.setContent(msgBody);

    try {
        myBuddy.create(account, bCfg);
        myBuddy.sendInstantMessage(prm);
        myBuddy.delete();
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }
}
1
user1506104 On

(For those of you who are wondering why it solved the problem)

To clarify Gangadhar's solution, the issue was caused by Garbage Collector. As per PJSIP Docs:

There are two problems with Java garbage collector (gc):

  1. it delays the destruction of Java objects (including pjsua2 objects), causing the code in object's destructor to be executed out of order
  2. the gc operation may be run on different thread, not previously registered to PJLIB

The solution was

application MUST immediately destroy pjsua2 objects using object's delete() method, instead of relying on the gc to clean up the object.

as you can see in his solution which called the MyBuddy's delete method:

try {
    myBuddy.create(account, bCfg);
    myBuddy.sendInstantMessage(prm);
    myBuddy.delete();
} catch (Exception e) {
    e.printStackTrace();
    return;
}
0
MARK002-MAB On

To avoid this kind of error, you have to register external thread (like Java thread) just after calling libCreate() method; otherwise, the the same error will be shown. PJSUA2 first register the current thread as the main thread inside libCreate(). So, to register different thread you have to do one of the following-

  1. Call libCreate() from the thread you want to register as main thread.
  2. Call libRegisterThread(name of the thread you want) after calling the libCreate(). The new thread will be registered as secondary thread.