Skip to content

Commit 0164a76

Browse files
committed
dylink: Synchronize dlsym calls (as well as dlopen) between threads
This is important for #18376.
1 parent 612577a commit 0164a76

14 files changed

+224
-96
lines changed

src/library_addfunction.js

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,27 +175,36 @@ mergeInto(LibraryManager.library, {
175175
}
176176
},
177177

178+
$getFunctionAddress__deps: ['$updateTableMap', '$functionsInTableMap'],
179+
$getFunctionAddress: function(func) {
180+
// First, create the map if this is the first use.
181+
if (!functionsInTableMap) {
182+
functionsInTableMap = new WeakMap();
183+
updateTableMap(0, wasmTable.length);
184+
}
185+
if (!functionsInTableMap.has(func)) {
186+
return 0;
187+
}
188+
return functionsInTableMap.get(func);
189+
},
190+
178191
/**
179192
* Add a function to the table.
180193
* 'sig' parameter is required if the function being added is a JS function.
181194
*/
182195
$addFunction__docs: '/** @param {string=} sig */',
183-
$addFunction__deps: ['$convertJsFunctionToWasm', '$updateTableMap',
196+
$addFunction__deps: ['$convertJsFunctionToWasm', '$getFunctionAddress',
184197
'$functionsInTableMap', '$getEmptyTableSlot',
185198
'$getWasmTableEntry', '$setWasmTableEntry'],
186199
$addFunction: function(func, sig) {
187200
#if ASSERTIONS
188201
assert(typeof func != 'undefined');
189202
#endif // ASSERTIONS
190-
191203
// Check if the function is already in the table, to ensure each function
192-
// gets a unique index. First, create the map if this is the first use.
193-
if (!functionsInTableMap) {
194-
functionsInTableMap = new WeakMap();
195-
updateTableMap(0, wasmTable.length);
196-
}
197-
if (functionsInTableMap.has(func)) {
198-
return functionsInTableMap.get(func);
204+
// gets a unique index.
205+
var rtn = getFunctionAddress(func);
206+
if (rtn) {
207+
return rtn;
199208
}
200209

201210
// It's not in the table, add it now.

src/library_async.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ mergeInto(LibraryManager.library, {
283283
// Exported functions in side modules are not listed in `Module["asm"]`,
284284
// So we should use `resolveGlobalSymbol` helper function, which is defined in `library_dylink.js`.
285285
if (!func) {
286-
func = resolveGlobalSymbol(name, false);
286+
func = resolveGlobalSymbol(name, false)[0];
287287
}
288288
#endif
289289
return func;

src/library_dylink.js

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ var LibraryDylink = {
3636
// First look for the orig$ symbol which is the symbols without
3737
// any legalization performed.
3838
sym = wasmImports['orig$' + symName];
39-
if (sym) return sym;
39+
if (sym) {
40+
symName = 'orig$' + symName;
41+
return [sym, symName];
42+
}
4043
}
4144
#endif
4245
if (isSymbolDefined(symName)) {
@@ -48,9 +51,10 @@ var LibraryDylink = {
4851
#if !DISABLE_EXCEPTION_CATCHING
4952
else if (symName.startsWith('__cxa_find_matching_catch_')) {
5053
sym = wasmImports['__cxa_find_matching_catch'];
54+
symName = __cxa_find_matching_catch;
5155
}
5256
#endif
53-
return sym;
57+
return [sym, symName];
5458
},
5559

5660
$GOT: {},
@@ -104,7 +108,7 @@ var LibraryDylink = {
104108
},
105109

106110
$updateGOT__internal: true,
107-
$updateGOT__deps: ['$GOT', '$isInternalSym', '$addFunction'],
111+
$updateGOT__deps: ['$GOT', '$isInternalSym', '$addFunction', '$getFunctionAddress'],
108112
$updateGOT: function(exports, replace) {
109113
#if DYLINK_DEBUG
110114
dbg("updateGOT: adding " + Object.keys(exports).length + " symbols");
@@ -192,7 +196,7 @@ var LibraryDylink = {
192196
#endif
193197
for (var symName in GOT) {
194198
if (GOT[symName].value == 0) {
195-
var value = resolveGlobalSymbol(symName, true)
199+
var value = resolveGlobalSymbol(symName, true)[0];
196200
if (!value && !GOT[symName].required) {
197201
// Ignore undefined symbols that are imported as weak.
198202
#if DYLINK_DEBUG
@@ -234,13 +238,15 @@ var LibraryDylink = {
234238
_dlopen_js__deps: [function() { error(dlopenMissingError); }],
235239
_emscripten_dlopen_js__deps: [function() { error(dlopenMissingError); }],
236240
_dlsym_js__deps: [function() { error(dlopenMissingError); }],
241+
_dlsym_catchup_js__deps: [function() { error(dlopenMissingError); }],
237242
#else
238243
$dlopenMissingError: `= ${dlopenMissingError}`,
239244
_dlopen_js__deps: ['$dlopenMissingError'],
240245
_emscripten_dlopen_js__deps: ['$dlopenMissingError'],
241246
_dlsym_js__deps: ['$dlopenMissingError'],
247+
_dlsym_catchup_js__deps: ['$dlopenMissingError'],
242248
#endif
243-
_dlopen_js: function(filename, flag) {
249+
_dlopen_js: function(handle) {
244250
abort(dlopenMissingError);
245251
},
246252
_emscripten_dlopen_js: function(handle, onsuccess, onerror, user_data) {
@@ -249,6 +255,9 @@ var LibraryDylink = {
249255
_dlsym_js: function(handle, symbol) {
250256
abort(dlopenMissingError);
251257
},
258+
_dlsym_catchup_js: function(handle, symbolIndex) {
259+
abort(dlopenMissingError);
260+
},
252261
_dlinit: function(main_dso_handle) {},
253262
#else // MAIN_MODULE != 0
254263
// dynamic linker/loader (a-la ld.so on ELF systems)
@@ -591,7 +600,7 @@ var LibraryDylink = {
591600
var moduleExports;
592601

593602
function resolveSymbol(sym) {
594-
var resolved = resolveGlobalSymbol(sym);
603+
var resolved = resolveGlobalSymbol(sym)[0];
595604
if (!resolved) {
596605
resolved = moduleExports[sym];
597606
}
@@ -1061,21 +1070,44 @@ var LibraryDylink = {
10611070
}
10621071
},
10631072

1073+
_dlsym_catchup_js__sig: 'ppp',
1074+
_dlsym_catchup_js: function(handle, symbolIndex) {
1075+
#if DYLINK_DEBUG
1076+
dbg("_dlsym_catchup: handle=" + ptrToString(handle) + " symbolIndex=" + symbolIndex);
1077+
#endif
1078+
var symDict = wasmImports;
1079+
if (handle != {{{ cDefine('RTLD_DEFAULT') }}}) {
1080+
var lib = LDSO.loadedLibsByHandle[handle];
1081+
symDict = lib.module;
1082+
}
1083+
var symName = Object.keys(symDict)[symbolIndex];
1084+
var sym = symDict[symName];
1085+
var result = addFunction(sym, sym.sig);
1086+
#if DYLINK_DEBUG
1087+
dbg('_dlsym_catchup: result=' + result);
1088+
#endif
1089+
return result;
1090+
},
1091+
10641092
// void* dlsym(void* handle, const char* symbol);
1065-
_dlsym_js__deps: ['$dlSetError'],
1093+
_dlsym_js__deps: ['$dlSetError', '$getFunctionAddress', '$addFunction'],
10661094
_dlsym_js__sig: 'ppp',
1067-
_dlsym_js: function(handle, symbol) {
1095+
_dlsym_js: function(handle, symbol, symbolIndex) {
10681096
// void *dlsym(void *restrict handle, const char *restrict name);
10691097
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
10701098
symbol = UTF8ToString(symbol);
10711099
var result;
1100+
var newSymIndex;
10721101

10731102
if (handle == {{{ cDefine('RTLD_DEFAULT') }}}) {
1074-
result = resolveGlobalSymbol(symbol, true);
1103+
var resolved = resolveGlobalSymbol(symbol, true);
1104+
result = resolved[0];
10751105
if (!result) {
10761106
dlSetError('Tried to lookup unknown symbol "' + symbol + '" in dynamic lib: RTLD_DEFAULT');
10771107
return 0;
10781108
}
1109+
name = resolved[1];
1110+
newSymIndex = Object.keys(wasmImports).indexOf(name);
10791111
} else {
10801112
var lib = LDSO.loadedLibsByHandle[handle];
10811113
#if ASSERTIONS
@@ -1085,16 +1117,21 @@ var LibraryDylink = {
10851117
dlSetError('Tried to lookup unknown symbol "' + symbol + '" in dynamic lib: ' + lib.name)
10861118
return 0;
10871119
}
1120+
newSymIndex = Object.keys(lib.module).indexOf(symbol);
10881121
#if !WASM_BIGINT
1089-
result = lib.module['orig$' + symbol];
1090-
if (!result)
1122+
var origSym = 'orig$' + symbol;
1123+
result = lib.module[origSym];
1124+
if (result) {
1125+
newSymIndex = Object.keys(lib.module).indexOf(origSym);
1126+
}
1127+
else
10911128
#endif
10921129
result = lib.module[symbol];
10931130
}
10941131

10951132
if (typeof result == 'function') {
10961133
#if DYLINK_DEBUG
1097-
dbg('dlsym: ' + symbol + ' getting table slot for: ' + result);
1134+
dbg('dlsym_js: ' + symbol + ' getting table slot for: ' + result);
10981135
#endif
10991136

11001137
#if ASYNCIFY
@@ -1103,14 +1140,26 @@ var LibraryDylink = {
11031140
result = result.orig;
11041141
}
11051142
#endif
1106-
// Insert the function into the wasm table. If its a direct wasm function
1107-
// the second argument will not be needed. If its a JS function we rely
1108-
// on the `sig` attribute being set based on the `<func>__sig` specified
1109-
// in library JS file.
1110-
result = addFunction(result, result.sig);
1143+
var addr = getFunctionAddress(result);
1144+
if (addr) {
1145+
#if DYLINK_DEBUG
1146+
dbg('symbol already exists in table: ' + symbol);
1147+
#endif
1148+
result = addr;
1149+
} else {
1150+
// Insert the function into the wasm table. If its a direct wasm
1151+
// function the second argument will not be needed. If its a JS
1152+
// function we rely on the `sig` attribute being set based on the
1153+
// `<func>__sig` specified in library JS file.
1154+
result = addFunction(result, result.sig);
1155+
#if DYLINK_DEBUG
1156+
dbg('adding symbol to table: ' + symbol);
1157+
#endif
1158+
{{{ makeSetValue('symbolIndex', 0, 'newSymIndex', '*') }}};
1159+
}
11111160
}
11121161
#if DYLINK_DEBUG
1113-
dbg('dlsym: ' + symbol + ' -> ' + result);
1162+
dbg('dlsym_js: ' + symbol + ' -> ' + result);
11141163
#endif
11151164
return result;
11161165
},

src/parseTools.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ function getEntryFunction() {
11141114
entryFunction = '_emscripten_proxy_main';
11151115
}
11161116
if (MAIN_MODULE) {
1117-
return `resolveGlobalSymbol('${entryFunction}');`
1117+
return `resolveGlobalSymbol('${entryFunction}')[0];`
11181118
}
11191119
return '_' + entryFunction;
11201120
}

0 commit comments

Comments
 (0)