Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic Thread Registration for External Threads in PJSUA2 #4318

Open
SangeMax97 opened this issue Feb 20, 2025 · 2 comments
Open

Automatic Thread Registration for External Threads in PJSUA2 #4318

SangeMax97 opened this issue Feb 20, 2025 · 2 comments

Comments

@SangeMax97
Copy link

Describe the feature

Description:
Currently, PJSUA2 requires explicit thread registration via pj_thread_register() for any external threads before calling PJLIB functions. This can lead to runtime errors and crashes if developers forget to register threads. To improve the developer experience, I propose the addition of a feature that automatically registers external threads when PJLIB functions are invoked from unregistered threads.

Proposed Solution:
Introduce an internal mechanism in PJSIP where endpoint.libRegisterThread() (or equivalent) is called automatically whenever PJLIB detects a function call from an unregistered external thread. This would provide the following benefits:

  1. Developer-Friendliness: Eliminates the need for manual thread registration, reducing the chances of assertion failures like:

    pj_thread_this: Assertion `!"Calling pjlib from unknown/external thread..."' failed
    
  2. Improved Stability: Ensures that all threads using PJLIB are properly registered, avoiding crashes or undefined behaviour.

  3. Backward Compatibility: Retain the ability to manually register threads for developers who prefer explicit control, but allow automatic registration as a fallback.

With the proposed feature, PJLIB would handle thread registration automatically, reducing boilerplate code and potential errors.

Describe alternatives you've considered

No response

Additional context

No response

@sauwming
Copy link
Member

This could be a good idea. There's one downside though. If it's done behind the screen, the number of registered threads could keep increasing, especially since we have no way to detect which threads are no longer used (as well as we currently have no mechanism to unregister such thread).

@andreas-wehrmann
Copy link
Contributor

I wrote a wrapper around PJSUA in C++ and ran into the same issue; so I did this, which works fine in my apps:

/* somewhere in your wrapper/library code have: */
static thread_local pj_thread_desc  this_pj_thread_desc;
static thread_local pj_thread_t*    this_pj_thread = nullptr;


static void checkThreadRegistry()
{
    /* this function makes sure the current thread of execution is registered to PJ */
    if( pj_thread_is_registered() ) { return; }
    pj_thread_register( NULL, this_pj_thread_desc, &this_pj_thread );
}

/* make sure, this function is the first thing called in every function you expose to users of your library */
CallId MyUserAgent::call(...)
{
    checkThreadRegistry();
    
    /* ...rest of the code... */
    return SomeCallIdOrNot;
}

It's not nice, it seems useless to call it upon every invocation of public functions, but it gets rid of headaches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants