Skip to content

Conversation

@juj
Copy link
Collaborator

@juj juj commented Apr 6, 2020

Fix cxa_thread_atexit() to properly register thread-local atexits, and not process-global atexits. (Also microcleanup code a little). Fixes #10809.

@juj juj force-pushed the fix_cxa_thread_atexit branch from 8ff4b0b to 9ded8c7 Compare April 6, 2020 13:09
Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with a test.

setThreadStatus: function() {},
#endif

runExitHandlers: function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a comment here that this is run on exit on each pthread, and on the main thread (I was confused before reading enough code to realize that - I hope I understood correctly?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, how about renaming exitHandlers to threadExitHandlers as IIUC this is just for pthreads, and not the main thread?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works, although that will be a bit redundant. These were named PThread.exitHandlers before, so having PThread.threadExitHandlers is duplicating the thread name. Perhaps that is worth it though.

#endif

// used in rust, clang when doing thread_local statics
__cxa_thread_atexit: 'pthread_cleanup_push',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pthread_cleanup_push has different semantics than __cxa_thread_atexit:

  1. When a thread terminates by calling pthread_exit(3), all clean-up
    handlers are executed as described in the preceding point.
    (Clean-up handlers are not called if the thread terminates by
    performing a return from the thread start function.)

So for full correctness, pthread_cleanup_* should use a different stack of cleanup handlers than the thread exit handlers. I'm not sure if this is an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will pthread_cleanup_push be available at all if !USE_PTHREADS? Should these thread_atexits just map to atexit if pthreads aren't available?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @abigailbunyan for the excellent observation. By the comment you post, pthread_cleanup_push handlers should only be called if thread performs an exit without returning. This PR does not change behavior around that: Both before and after this PR, pthread_cleanup_push handlers are called on all kinds of exits. So let's deal with that as a followup.

pthread_cleanup_push is available in single-threaded programs, and goes via completely different implementation in library_pthread_stub.js - which does map to atexit already.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though now I realize routing directly to atexit in singlethreaded builds generates smaller code size, so using that.

@sbc100
Copy link
Collaborator

sbc100 commented Apr 29, 2020

I wonder if we can rely on the native libc++abi implementation. I've started experimenting with it here and it might be possible to use this in all cases: #11040

@juj juj force-pushed the fix_cxa_thread_atexit branch from 9ded8c7 to 30de04e Compare June 17, 2020 10:28
@juj juj merged commit 1927cff into emscripten-core:master Jun 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TLS struct destructors not called when thread is not joined

4 participants