Skip to content

Commit b86798a

Browse files
authored
Move PROXY_TO_PTHREAD handling into native code. NFC (#17153)
Fixes: #17144
1 parent 4549d9d commit b86798a

14 files changed

+56
-56
lines changed

emcc.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,10 @@ def phase_linker_setup(options, state, newargs, user_settings):
17411741
settings.EXPECT_MAIN = 0
17421742
else:
17431743
assert not settings.EXPORTED_FUNCTIONS
1744-
settings.EXPORTED_FUNCTIONS = ['_main']
1744+
# With PROXY_TO_PTHREAD we don't export `main` at all but instead
1745+
# we export `emscripten_proxy_main` (elsewhwere).
1746+
if not settings.PROXY_TO_PTHREAD:
1747+
settings.EXPORTED_FUNCTIONS = ['_main']
17451748

17461749
if settings.STANDALONE_WASM:
17471750
# In STANDALONE_WASM mode we either build a command or a reactor.
@@ -2519,12 +2522,6 @@ def check_memory_setting(setting):
25192522
# they are indirect calls, since that is what they do - we can't see their
25202523
# targets statically.
25212524
settings.ASYNCIFY_IMPORTS += ['invoke_*']
2522-
# with pthreads we may call main through the __call_main mechanism, which can
2523-
# therefore reach anything in the program, so mark it as possibly causing a
2524-
# sleep (the asyncify analysis doesn't look through JS, just wasm, so it can't
2525-
# see what it itself calls)
2526-
if settings.USE_PTHREADS:
2527-
settings.ASYNCIFY_IMPORTS += ['__call_main']
25282525
# add the default imports
25292526
settings.ASYNCIFY_IMPORTS += DEFAULT_ASYNCIFY_IMPORTS
25302527

emscripten.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def update_settings_glue(wasm_file, metadata):
147147
if settings.MEMORY64:
148148
assert '--enable-memory64' in settings.BINARYEN_FEATURES
149149

150-
settings.HAS_MAIN = bool(settings.MAIN_MODULE) or settings.STANDALONE_WASM or 'main' in settings.WASM_EXPORTS or '__main_argc_argv' in settings.WASM_EXPORTS
150+
settings.HAS_MAIN = bool(settings.MAIN_MODULE) or settings.PROXY_TO_PTHREAD or settings.STANDALONE_WASM or 'main' in settings.WASM_EXPORTS or '__main_argc_argv' in settings.WASM_EXPORTS
151151

152152
# When using dynamic linking the main function might be in a side module.
153153
# To be safe assume they do take input parametes.
@@ -220,12 +220,6 @@ def report_missing_symbols(js_library_funcs):
220220
# In this mode we never expect _main in the export list.
221221
return
222222

223-
# PROXY_TO_PTHREAD only makes sense with a main(), so error if one is
224-
# missing. note that when main() might arrive from another module we cannot
225-
# error here.
226-
if settings.PROXY_TO_PTHREAD and not settings.HAS_MAIN:
227-
exit_with_error('PROXY_TO_PTHREAD proxies main() for you, but no main exists')
228-
229223
if settings.IGNORE_MISSING_MAIN:
230224
# The default mode for emscripten is to ignore the missing main function allowing
231225
# maximum compatibility.

src/jsifier.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ global.proxiedFunctionTable = ['null'/* Reserve index 0 for an undefined functio
1717

1818
// Mangles the given C/JS side function name to assembly level function name (adds an underscore)
1919
function mangleCSymbolName(f) {
20+
if (f === '__main_argc_argv') {
21+
f = 'main';
22+
}
2023
return f[0] == '$' ? f.substr(1) : '_' + f;
2124
}
2225

@@ -53,6 +56,9 @@ function isDefined(symName) {
5356
if (WASM_EXPORTS.has(symName) || SIDE_MODULE_EXPORTS.has(symName)) {
5457
return true;
5558
}
59+
if (symName == '__main_argc_argv' && SIDE_MODULE_EXPORTS.has('main')) {
60+
return true;
61+
}
5662
// 'invoke_' symbols are created at runtime in libary_dylink.py so can
5763
// always be considered as defined.
5864
if (RELOCATABLE && symName.startsWith('invoke_')) {
@@ -208,9 +214,13 @@ function ${name}(${args}) {
208214
}
209215
const isWeakImport = WEAK_IMPORTS.has(ident);
210216
if (!isDefined(ident) && !isWeakImport) {
217+
if (PROXY_TO_PTHREAD && !MAIN_MODULE && ident == '__main_argc_argv') {
218+
error('PROXY_TO_PTHREAD proxies main() for you, but no main exists');
219+
return;
220+
}
211221
let undefinedSym = ident;
212222
if (ident === '__main_argc_argv') {
213-
undefinedSym = 'main';
223+
undefinedSym = 'main/__main_argc_argv';
214224
}
215225
let msg = 'undefined symbol: ' + undefinedSym;
216226
if (dependent) msg += ` (referenced by ${dependent})`;
@@ -224,7 +234,7 @@ function ${name}(${args}) {
224234
} else if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) {
225235
warn(msg);
226236
}
227-
if (undefinedSym === 'main' && STANDALONE_WASM) {
237+
if (ident === '__main_argc_argv' && STANDALONE_WASM) {
228238
warn('To build in STANDALONE_WASM mode without a main(), use emcc --no-entry');
229239
}
230240
}

src/library_dylink.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,16 +475,17 @@ var LibraryDylink = {
475475

476476
// Export native export on the Module object.
477477
// TODO(sbc): Do all users want this? Should we skip this by default?
478-
#if !hasExportedFunction('_main')
479-
// If the main module doesn't define main it could be defined in one of
480-
// the side module, and we need to handle the mangled named.
481-
var module_sym = asmjsMangle(sym == '__main_argc_argv' ? 'main' : sym);
482-
#else
483478
var module_sym = asmjsMangle(sym);
484-
#endif
485479
if (!Module.hasOwnProperty(module_sym)) {
486480
Module[module_sym] = exports[sym];
487481
}
482+
#if !hasExportedFunction('_main')
483+
// If the main module doesn't define main it could be defined in one of
484+
// the side modules, and we need to handle the mangled named.
485+
if (sym == '__main_argc_argv') {
486+
Module['_main'] = exports[sym];
487+
}
488+
#endif
488489
}
489490
},
490491

src/library_pthread.js

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -807,30 +807,6 @@ var LibraryPThread = {
807807
return 0;
808808
},
809809

810-
#if PROXY_TO_PTHREAD
811-
__call_main__deps: ['exit', '$exitOnMainThread'],
812-
__call_main: function(argc, argv) {
813-
#if !EXIT_RUNTIME
814-
// EXIT_RUNTIME==0 set, keeping main thread alive by default.
815-
noExitRuntime = true;
816-
#endif
817-
var returnCode = {{{ exportedAsmFunc('_main') }}}(argc, argv);
818-
#if EXIT_RUNTIME
819-
if (!keepRuntimeAlive()) {
820-
// exitRuntime enabled, proxied main() finished in a pthread, shut down the process.
821-
#if PTHREADS_DEBUG
822-
err('Proxied main thread finished with return code ' + returnCode + '. EXIT_RUNTIME=1 set, quitting process.');
823-
#endif
824-
exitOnMainThread(returnCode);
825-
}
826-
#else
827-
#if PTHREADS_DEBUG
828-
err('Proxied main thread finished with return code ' + returnCode + '. EXIT_RUNTIME=0 set, so keeping main thread alive for asynchronous event operations.');
829-
#endif
830-
#endif
831-
},
832-
#endif
833-
834810
// This function is call by a pthread to signal that exit() was called and
835811
// that the entire process should exit.
836812
// This function is always called from a pthread, but is executed on the

system/lib/pthread/emscripten_proxy_main.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,30 @@
66
*/
77

88
#include <pthread.h>
9+
#include <stdlib.h>
910

1011
#include <emscripten.h>
1112
#include <emscripten/stack.h>
1213
#include <emscripten/threading.h>
14+
#include <emscripten/eventloop.h>
1315

1416
static int _main_argc;
1517
static char** _main_argv;
1618

17-
extern void __call_main(int argc, char** argv);
19+
int __main_argc_argv(int argc, char *argv[]);
20+
21+
weak int __main_void(void) {
22+
return __main_argc_argv(_main_argc, _main_argv);
23+
}
1824

1925
static void* _main_thread(void* param) {
2026
// This is the main runtime thread for the application.
2127
emscripten_set_thread_name(pthread_self(), "Application main thread");
22-
__call_main(_main_argc, _main_argv);
28+
// Will either call user's __main_void or weak version above.
29+
int rtn = __main_void();
30+
if (!emscripten_runtime_keepalive_check()) {
31+
exit(rtn);
32+
}
2333
return NULL;
2434
}
2535

tests/other/metadce/test_metadce_minimal_pthreads.exports

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ A
22
B
33
C
44
D
5-
E
65
o
76
p
87
q

tests/other/metadce/test_metadce_minimal_pthreads.funcs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ $emscripten_stack_set_limits
4646
$get_tasks_for_thread
4747
$init_file_lock
4848
$init_mparams
49-
$main
5049
$memset
5150
$pthread_mutexattr_destroy
5251
$sbrk
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16131
1+
16048
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
18331
1+
18318

0 commit comments

Comments
 (0)