Re: Thread safety problem with pj_thread_is_registered

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



You need to allocate memory for the thread_desc on the heap. Your code was allocating it on the stack, where it would be overwritten after your function returned.  I posted some example code to the list some time ago. - Bill

On 4/13/2016 10:33 PM, 屈振华 wrote:
​​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)
{

#if PJ_HAS_THREADS
    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 "
                 "thread"));
    }

    /* 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) < sizeof(thread->obj_name)-1)
    pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name),
             cstr_thread_name, thread->thread);
    else
    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;
    }



_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux