Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1883,6 +1883,7 @@ def default_setting(name, new_default):
'_emscripten_tls_init',
'_pthread_self',
'_pthread_testcancel',
'_pthread_self',
]
# Some of these symbols are using by worker.js but otherwise unreferenced.
# Because emitDCEGraph only considered the main js file, and not worker.js
Expand Down Expand Up @@ -1926,9 +1927,8 @@ def default_setting(name, new_default):
if settings.USE_PTHREADS:
# memalign is used to ensure allocated thread stacks are aligned.
settings.EXPORTED_FUNCTIONS += ['_memalign']

if settings.MINIMAL_RUNTIME:
building.user_requested_exports.add('exit')
# _exit is called to shutdown the process
settings.EXPORTED_FUNCTIONS += ['_exit']

if settings.PROXY_TO_PTHREAD:
settings.EXPORTED_FUNCTIONS += ['_emscripten_proxy_main']
Expand Down Expand Up @@ -2209,6 +2209,9 @@ def check_memory_setting(setting):
# enables the --post-emscripten pass
settings.GLOBAL_BASE = 1024

if settings.EXIT_RUNTIME and not settings.STANDALONE_WASM:
settings.EXPORTED_FUNCTIONS += ['_exit']

# various settings require malloc/free support from JS
if settings.RELOCATABLE or \
settings.BUILD_AS_WORKER or \
Expand Down
49 changes: 16 additions & 33 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,6 @@ LibraryManager.library = {
return -1;
},

exit__sig: 'vi',
#if MINIMAL_RUNTIME
// minimal runtime doesn't do any exit cleanup handling so just
// map exit directly to the lower-level proc_exit syscall.
exit: 'proc_exit',
$exit: 'exit',
#else
exit: function(status) {
// void _exit(int status);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
exit(status);
},
#endif

// fork, spawn, etc. all return an error as we don't support multiple
// processes.
fork__deps: ['$setErrNo'],
Expand Down Expand Up @@ -426,22 +412,6 @@ LibraryManager.library = {
// stdlib.h
// ==========================================================================

#if MINIMAL_RUNTIME && !EXIT_RUNTIME
atexit__sig: 'v', // atexit unsupported in MINIMAL_RUNTIME
atexit: function(){},
__cxa_atexit: function(){},
#else
atexit__proxy: 'sync',
atexit__sig: 'iii',
atexit: function(func, arg) {
#if EXIT_RUNTIME
__ATEXIT__.unshift({ func: func, arg: arg });
#endif
},
__cxa_atexit: 'atexit',

#endif

// TODO: There are currently two abort() functions that get imported to asm module scope: the built-in runtime function abort(),
// and this function _abort(). Remove one of these, importing two functions for the same purpose is wasteful.
abort__sig: 'v',
Expand Down Expand Up @@ -3579,9 +3549,13 @@ LibraryManager.library = {
throw 'unwind';
},

#if MINIMAL_RUNTIME
emscripten_force_exit__deps: ['exit'],
emscripten_force_exit__deps: [
#if MINIMAL_RUNTIME || hasExportedFunction('_exit')
'exit',
#else
'proc_exit'
#endif
],
emscripten_force_exit__proxy: 'sync',
emscripten_force_exit__sig: 'vi',
emscripten_force_exit: function(status) {
Expand All @@ -3595,7 +3569,10 @@ LibraryManager.library = {
#else
noExitRuntime = false;
runtimeKeepaliveCounter = 0;
exit(status);
#if hasExportedFunction('_exit')
_exit(status);
#else
_proc_exit(status);
#endif
},

Expand Down Expand Up @@ -3684,7 +3661,13 @@ LibraryManager.library = {
if (ENVIRONMENT_IS_PTHREAD) __emscripten_thread_exit(EXITSTATUS);
else
#endif
#if EXIT_RUNTIME
//console.error("calling C exit");
_exit(EXITSTATUS);
#else
//console.error("bypassing C exit");
procExit(EXITSTATUS);
#endif
} catch (e) {
handleException(e);
}
Expand Down
4 changes: 0 additions & 4 deletions src/library_async.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ mergeInto(LibraryManager.library, {
Normal: 0,
Unwinding: 1,
Rewinding: 2,
Disabled: 3,
},
state: 0,
StackSize: {{{ ASYNCIFY_STACK_SIZE }}},
Expand Down Expand Up @@ -210,9 +209,6 @@ mergeInto(LibraryManager.library, {
},

handleSleep: function(startAsync) {
#if ASSERTIONS
assert(Asyncify.state !== Asyncify.State.Disabled, 'Asyncify cannot be done during or after the runtime exits');
#endif
if (ABORT) return;
#if ASYNCIFY_DEBUG
err('ASYNCIFY: handleSleep ' + Asyncify.state);
Expand Down
10 changes: 1 addition & 9 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ var LibraryPThread = {
},
// Maps pthread_t to pthread info objects
pthreads: {},
threadExitHandlers: [], // An array of C functions to run when this thread exits.

#if PTHREADS_PROFILING
createProfilerBlock: function(pthreadPtr) {
Expand Down Expand Up @@ -303,7 +302,7 @@ var LibraryPThread = {
err("exitProcess requested by worker");
#endif
try {
exit(d['returnCode']);
{{{ exportedAsmFunc('_exit') }}}(d['returnCode']);
} catch (e) {
handleException(e);
}
Expand Down Expand Up @@ -928,13 +927,6 @@ var LibraryPThread = {
postMessage({ 'cmd': 'exit' });
},

__cxa_thread_atexit__sig: 'vii',
__cxa_thread_atexit: function(routine, arg) {
PThread.threadExitHandlers.push(function() { {{{ makeDynCall('vi', 'routine') }}}(arg) });
},
__cxa_thread_atexit_impl: '__cxa_thread_atexit',


// Returns 0 on success, or one of the values -ETIMEDOUT, -EWOULDBLOCK or -EINVAL on error.
emscripten_futex_wait__deps: ['emscripten_main_thread_process_queued_calls'],
emscripten_futex_wait: function(addr, val, timeout) {
Expand Down
3 changes: 0 additions & 3 deletions src/library_pthread_stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ var LibraryPThreadStub = {
// Do nothing.
}
},

__cxa_thread_atexit: 'atexit',
__cxa_thread_atexit_impl: 'atexit',
};

mergeInto(LibraryManager.library, LibraryPThreadStub);
2 changes: 2 additions & 0 deletions src/library_wasi.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ var WasiLibrary = {
#if MINIMAL_RUNTIME
throw 'exit(' + code + ')';
#else
//out('proc_exit');
procExit(code);
//out('proc_exit done');
#endif
},

Expand Down
34 changes: 24 additions & 10 deletions src/postamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ function ExitStatus(status) {
}

var calledMain = false;
var implicitExit = false;

#if STANDALONE_WASM && MAIN_READS_PARAMS
var mainArgs = undefined;
Expand Down Expand Up @@ -190,8 +191,19 @@ function callMain(args) {
assert(ret == 0, '_emscripten_proxy_main failed to start proxy thread: ' + ret);
#endif
#else
// if we're not running an evented main loop, it's time to exit
exit(ret, /* implicit = */ true);
//console.error("implicitExit!");
implicitExit = true;
#if EXIT_RUNTIME
if (!keepRuntimeAlive()) {
// Perform a full C _exit which will end up calling procExit.
//console.error("calling C exit");
_exit(ret);
// unreachable
}
#endif
//console.error("bypassing C exit");
procExit(ret);
// unreachable
}
catch (e) {
// Certain exception types we do not treat as errors since they are used for
Expand All @@ -212,6 +224,7 @@ function callMain(args) {
#endif // !PROXY_TO_PTHREAD
} finally {
calledMain = true;
implicitExit = false;

#if ABORT_ON_WASM_EXCEPTIONS
// See abortWrapperDepth in preamble.js!
Expand Down Expand Up @@ -407,21 +420,20 @@ function checkUnflushedContent() {
#endif // EXIT_RUNTIME
#endif // ASSERTIONS

/** @param {boolean|number=} implicit */
function exit(status, implicit) {
function procExit(status) {
//console.error('procExit');
EXITSTATUS = status;

#if ASSERTIONS
#if EXIT_RUNTIME == 0
checkUnflushedContent();
#endif // EXIT_RUNTIME
#endif // ASSERTIONS

#if USE_PTHREADS
if (!implicit) {
if (!implicitExit) {
if (ENVIRONMENT_IS_PTHREAD) {
#if ASSERTIONS
err('Pthread 0x' + _pthread_self().toString(16) + ' called exit(), posting exitProcess.');
err('Pthread 0x' + _pthread_self().toString(16) + ' called procExit(), posting exitProcess.');
#endif
// When running in a pthread we propagate the exit back to the main thread
// where it can decide if the whole process should be shut down or not.
Expand All @@ -431,16 +443,16 @@ function exit(status, implicit) {
throw new ExitStatus(status);
} else {
#if ASSERTIONS
err('main thread called exit: keepRuntimeAlive=' + keepRuntimeAlive() + ' (counter=' + runtimeKeepaliveCounter + ')');
err('main thread called procExit: keepRuntimeAlive=' + keepRuntimeAlive() + ' (counter=' + runtimeKeepaliveCounter + ')');
#endif
}
}
#endif

if (keepRuntimeAlive()) {
#if ASSERTIONS
// if exit() was called, we may warn the user if the runtime isn't actually being shut down
if (!implicit) {
// if procExit() was called, we may warn the user if the runtime isn't actually being shut down
if (!implicitExit) {
#if EXIT_RUNTIME == 0
var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
#else
Expand Down Expand Up @@ -473,6 +485,8 @@ function procExit(code) {
#endif
ABORT = true;
}

//console.error('calling quit_');
quit_(code, new ExitStatus(code));
}

Expand Down
6 changes: 2 additions & 4 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,18 +401,16 @@ function preMain() {
#endif

function exitRuntime() {
#if ASYNCIFY && ASSERTIONS
// ASYNCIFY cannot be used once the runtime starts shutting down.
Asyncify.state = Asyncify.State.Disabled;
#endif
#if STACK_OVERFLOW_CHECK
checkStackCookie();
#endif
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread.
#endif
#if EXIT_RUNTIME
//console.error(__ATEXIT__);
callRuntimeCallbacks(__ATEXIT__);
//console.error('done exit callbacks');
<<< ATEXITS >>>
#endif
runtimeExited = true;
Expand Down
1 change: 1 addition & 0 deletions system/lib/libc/musl/src/stdio/__stdio_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ static void close_file(FILE *f)

void __stdio_exit(void)
{
//puts("__stdio_exit");
FILE *f;
for (f=*__ofl_lock(); f; f=f->next) close_file(f);
close_file(__stdin_used);
Expand Down
5 changes: 2 additions & 3 deletions system/lib/libc/musl/src/thread/pthread_key_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ int __pthread_key_delete(pthread_key_t k)
}

#ifdef __EMSCRIPTEN__
void EMSCRIPTEN_KEEPALIVE __pthread_tsd_run_dtors()
#else
void __pthread_tsd_run_dtors()
EMSCRIPTEN_KEEPALIVE
#endif
void __pthread_tsd_run_dtors()
{
pthread_t self = __pthread_self();
int i, j, not_finished = self->tsd_used;
Expand Down
2 changes: 1 addition & 1 deletion system/lib/libcxxabi/include/cxxabi.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ __cxa_decrement_exception_refcount(void *primary_exception) _NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() _NOEXCEPT;
extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() _NOEXCEPT;

#if defined(__linux__) || defined(__Fuchsia__)
#if defined(__linux__) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
// Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI.
// https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables
extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void *), void *,
Expand Down
Loading