[pjsip] Thread safety problem with pj_thread_is_registered

屈振华 qzhua3 at gmail.com
Wed Apr 13 22:33:25 EDT 2016

​​When using pjlib in  threads  other than pj created, I found these errors:

    pj_assert(!"Calling pjlib from unknown/external thread. You must "
           "register external threads with pj_thread_register() "
           "before calling any pjlib functions.");

​I found some solution on the web ,

   1. bool ice_register_thread()
   2. {
   3.     if(!pj_thread_is_registered())
   4.     {
   5.         pj_thread_desc desc;
   6.         pj_thread_t* thed;
   7.         if (pj_thread_register(NULL,desc,&thed) == PJ_SUCCESS)
   8.         {
   9.             return true;
   10.         }
   11.     }
   12.     return false;
   13. }

​But this is risky in practice. I found the pj_thread_register in
os_core_unix.c​ has converted the  input parameter pj_thread_desc desc to
(pj_thread_t *) and uses it as a pointer to access signature, signature2,
thread and obj_name.
​  So the above code is will cause illegal memory access. ​ I tried to
solve this problem by defining :
 > pj_thread_t thread;
 > pj_thread_desc desc=(pj_thread_desc)&thread;
However, it has compiling errors: incomplete type 'pj_thread_t', scince
this data type is only internally defined in os_core_unix.c and and cannot
be used from outside.

So what is the right way to perform pj_thread_register ?​

PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,
                     pj_thread_desc desc,
                     pj_thread_t **ptr_thread)

    char stack_ptr;
    pj_status_t rc;
    pj_thread_t *thread = (pj_thread_t *)desc;
    pj_str_t thread_name = pj_str((char*)cstr_thread_name);

    /* Size sanity check. */
    if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {
    pj_assert(!"Not enough pj_thread_desc size!");
    return PJ_EBUG;

    /* Warn if this thread has been registered before */
    if (pj_thread_local_get (thread_tls_id) != 0) {
    // 2006-02-26 bennylp:
    //  This wouldn't work in all cases!.
    //  If thread is created by external module (e.g. sound thread),
    //  thread may be reused while the pool used for the thread descriptor
    //  has been deleted by application.
    //*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);
        //return PJ_SUCCESS;
    PJ_LOG(4,(THIS_FILE, "Info: possibly re-registering existing "

    /* On the other hand, also warn if the thread descriptor buffer seem to
     * have been used to register other threads.
    pj_assert(thread->signature1 != SIGNATURE1 ||
          thread->signature2 != SIGNATURE2 ||
          (thread->thread == pthread_self()));

    /* Initialize and set the thread entry. */
    pj_bzero(desc, sizeof(struct pj_thread_t));
    thread->thread = pthread_self();
    thread->signature1 = SIGNATURE1;
    thread->signature2 = SIGNATURE2;

    if(cstr_thread_name && pj_strlen(&thread_name) <
    pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name),
             cstr_thread_name, thread->thread);
    pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name),
             "thr%p", (void*)thread->thread);

    rc = pj_thread_local_set(thread_tls_id, thread);
    if (rc != PJ_SUCCESS) {
    pj_bzero(desc, sizeof(struct pj_thread_t));
    return rc;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20160414/6c5c047c/attachment-0002.html>

More information about the pjsip mailing list