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 ,
- bool ice_register_thread()
- {
- if(!pj_thread_is_registered())
- {
- pj_thread_desc desc;
- pj_thread_t* thed;
- if (pj_thread_register(NULL,desc,&thed) == PJ_SUCCESS)
- {
- return true;
- }
- }
- return false;
- }
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;
}