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

The automatic "thread stop" functionality relies on non-standard behaviour #24357

Open
3 tasks
mattcaswell opened this issue May 10, 2024 · 0 comments
Open
3 tasks
Assignees
Labels
branch: master Merge to master branch branch: 3.0 Merge to openssl-3.0 branch branch: 3.1 Merge to openssl-3.1 branch: 3.2 Merge to openssl-3.2 branch: 3.3 Merge to openssl-3.3 epic Body of work that has to be broken down into more manageably sized issues triaged: bug The issue/pr is/fixes a bug

Comments

@mattcaswell
Copy link
Member

mattcaswell commented May 10, 2024

We have the function OPENSSL_thread_stop(_ex) so that an application can explicitly clean up thread local data when a thread is no longer going to be using OpenSSL. Most applications don't need to use it though because our implementation automatically detects when a thread is exiting and cleans up the thread local data automatically.

The automatic detection of a thread exiting works by registering a thread destructor callback when initialising a thread local data key:

openssl/crypto/initthread.c

Lines 195 to 209 in d318411

static void init_thread_destructor(void *hands)
{
init_thread_stop(NULL, (THREAD_EVENT_HANDLER **)hands);
init_thread_remove_handlers(hands);
OPENSSL_free(hands);
}
int ossl_init_thread(void)
{
if (!CRYPTO_THREAD_init_local(&destructor_key.value,
init_thread_destructor))
return 0;
return 1;
}

Other sections of the code also use thread local keys but they rely on the centralised detection of a thread exiting for cleanup. They simply register a callback with the centralised mechanism and the callback gets called when cleanup is necessary. It is done this way for portability reasons so that the same mechanism can be used on all platforms.

However, at least with pthreads on Linux (windows threads not tested), it was found during the development of #24344 that the thread local data for the RCU code was being set to NULL before the centralised callback mechanism could clean it up. This turns out to be because, with pthreads on Linux the thread local data is cleaned up by the platform in the order that the thread local keys were created. If there is no destructor then the thread local data just gets set to NULL. So if a thread local key gets created before the centralised thread local key, then thread local data is always set to NULL before the centralised handling can clean it up.

The workaround for this problem in #24344 is to ensure that the centralised thread local key is always created first. But this relies on the ordering that thread local data is cleaned up being standard for all pthreads implementations. AFAIK this is not the case??

@mattcaswell mattcaswell added branch: master Merge to master branch triaged: bug The issue/pr is/fixes a bug branch: 3.0 Merge to openssl-3.0 branch branch: 3.1 Merge to openssl-3.1 branch: 3.2 Merge to openssl-3.2 branch: 3.3 Merge to openssl-3.3 labels May 10, 2024
@nhorman nhorman added the epic Body of work that has to be broken down into more manageably sized issues label May 13, 2024
@nhorman nhorman self-assigned this May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
branch: master Merge to master branch branch: 3.0 Merge to openssl-3.0 branch branch: 3.1 Merge to openssl-3.1 branch: 3.2 Merge to openssl-3.2 branch: 3.3 Merge to openssl-3.3 epic Body of work that has to be broken down into more manageably sized issues triaged: bug The issue/pr is/fixes a bug
Projects
Status: Refine
Development

No branches or pull requests

2 participants