Skip to content

Commit 9eff02b

Browse files
authored
Move LD_LIBRARY_PATH handling to native code. NFC (#19321)
Split out from #19310
1 parent f2cca1a commit 9eff02b

File tree

3 files changed

+61
-29
lines changed

3 files changed

+61
-29
lines changed

src/library_dylink.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,25 +1071,6 @@ var LibraryDylink = {
10711071
filename = PATH.normalize(filename);
10721072
var searchpaths = [];
10731073

1074-
var isValidFile = (filename) => {
1075-
var target = FS.findObject(filename);
1076-
return target && !target.isFolder && !target.isDevice;
1077-
};
1078-
1079-
if (!isValidFile(filename)) {
1080-
if (ENV['LD_LIBRARY_PATH']) {
1081-
searchpaths = ENV['LD_LIBRARY_PATH'].split(':');
1082-
}
1083-
1084-
for (var ident in searchpaths) {
1085-
var searchfile = PATH.join2(searchpaths[ident], filename);
1086-
if (isValidFile(searchfile)) {
1087-
filename = searchfile;
1088-
break;
1089-
}
1090-
}
1091-
}
1092-
10931074
var global = Boolean(flags & {{{ cDefs.RTLD_GLOBAL }}});
10941075
var localScope = global ? null : {};
10951076

system/lib/libc/dynlink.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <stdio.h>
1919
#include <stdlib.h>
2020
#include <string.h>
21+
#include <sys/stat.h>
2122

2223
#include <emscripten/console.h>
2324
#include <emscripten/threading.h>
@@ -441,6 +442,37 @@ static void dlopen_onerror(struct dso* dso, void* user_data) {
441442
free(data);
442443
}
443444

445+
// Modified version of path_open from musl/ldso/dynlink.c
446+
static int path_find(const char *name, const char *s, char *buf, size_t buf_size) {
447+
size_t l;
448+
int fd;
449+
for (;;) {
450+
s += strspn(s, ":\n");
451+
l = strcspn(s, ":\n");
452+
if (l-1 >= INT_MAX) return -1;
453+
if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) {
454+
dbg("dlopen: path_find: %s", buf);
455+
struct stat statbuf;
456+
if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
457+
return 0;
458+
}
459+
switch (errno) {
460+
case ENOENT:
461+
case ENOTDIR:
462+
case EACCES:
463+
case ENAMETOOLONG:
464+
break;
465+
default:
466+
dbg("dlopen: path_find failed: %s", strerror(errno));
467+
/* Any negative value but -1 will inhibit
468+
* futher path search. */
469+
return -2;
470+
}
471+
}
472+
s += l;
473+
}
474+
}
475+
444476
// Internal version of dlopen with typed return value.
445477
// Without this, the compiler won't tell us if we have the wrong return type.
446478
static struct dso* _dlopen(const char* file, int flags) {
@@ -462,6 +494,16 @@ static struct dso* _dlopen(const char* file, int flags) {
462494

463495
struct dso* p;
464496

497+
/* Resolve filename using LD_LIBRARY_PATH */
498+
char buf[2*NAME_MAX+2];
499+
if (!strchr(file, '/')) {
500+
const char* env_path = getenv("LD_LIBRARY_PATH");
501+
if (env_path && path_find(file, env_path, buf, sizeof buf) == 0) {
502+
dbg("dlopen: found in LD_LIBRARY_PATH: %s", buf);
503+
file = buf;
504+
}
505+
}
506+
465507
/* Search for the name to see if it's already loaded */
466508
for (struct dlevent* e = head; e; e = e->next) {
467509
if (e->sym_index == -1 && !strcmp(e->dso->name, file)) {

test/test_other.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6407,10 +6407,11 @@ def test_ld_library_path(self):
64076407
''')
64086408
create_file('pre.js', r'''
64096409
Module['preRun'] = function () {
6410-
ENV['LD_LIBRARY_PATH']='/lib:/usr/lib';
6410+
ENV['LD_LIBRARY_PATH']='/lib:/usr/lib:/usr/local/lib';
64116411
};
64126412
''')
64136413
create_file('main.c', r'''
6414+
#include <assert.h>
64146415
#include <stdio.h>
64156416
#include <stdlib.h>
64166417
#include <string.h>
@@ -6422,22 +6423,30 @@ def test_ld_library_path(self):
64226423
double (*f2)(double);
64236424

64246425
h = dlopen("libhello1.wasm", RTLD_NOW);
6426+
assert(h);
64256427
f = dlsym(h, "hello1");
6428+
assert(f);
64266429
f();
64276430
dlclose(h);
64286431

64296432
h = dlopen("libhello2.wasm", RTLD_NOW);
6433+
assert(h);
64306434
f = dlsym(h, "hello2");
6435+
assert(f);
64316436
f();
64326437
dlclose(h);
64336438

64346439
h = dlopen("libhello3.wasm", RTLD_NOW);
6440+
assert(h);
64356441
f = dlsym(h, "hello3");
6442+
assert(f);
64366443
f();
64376444
dlclose(h);
64386445

64396446
h = dlopen("/usr/local/lib/libhello4.wasm", RTLD_NOW);
6447+
assert(h);
64406448
f2 = dlsym(h, "hello4");
6449+
assert(f2);
64416450
double result = f2(5.5);
64426451
dlclose(h);
64436452

@@ -6447,16 +6456,16 @@ def test_ld_library_path(self):
64476456
return 0;
64486457
}
64496458
''')
6450-
self.run_process([EMCC, '-o', 'libhello1.wasm', 'hello1.c', '-sSIDE_MODULE'])
6451-
self.run_process([EMCC, '-o', 'libhello2.wasm', 'hello2.c', '-sSIDE_MODULE'])
6452-
self.run_process([EMCC, '-o', 'libhello3.wasm', 'hello3.c', '-sSIDE_MODULE'])
6453-
self.run_process([EMCC, '-o', 'libhello4.wasm', 'hello4.c', '-sSIDE_MODULE'])
6459+
self.run_process([EMCC, '-o', 'hello1.wasm', 'hello1.c', '-sSIDE_MODULE'])
6460+
self.run_process([EMCC, '-o', 'hello2.wasm', 'hello2.c', '-sSIDE_MODULE'])
6461+
self.run_process([EMCC, '-o', 'hello3.wasm', 'hello3.c', '-sSIDE_MODULE'])
6462+
self.run_process([EMCC, '-o', 'hello4.wasm', 'hello4.c', '-sSIDE_MODULE'])
64546463
self.run_process([EMCC, '--profiling-funcs', '-o', 'main.js', 'main.c', '-sMAIN_MODULE=2', '-sINITIAL_MEMORY=32Mb',
6455-
'--embed-file', 'libhello1.wasm@/lib/libhello1.wasm',
6456-
'--embed-file', 'libhello2.wasm@/usr/lib/libhello2.wasm',
6457-
'--embed-file', 'libhello3.wasm@/libhello3.wasm',
6458-
'--embed-file', 'libhello4.wasm@/usr/local/lib/libhello4.wasm',
6459-
'libhello1.wasm', 'libhello2.wasm', 'libhello3.wasm', 'libhello4.wasm', '-sNO_AUTOLOAD_DYLIBS',
6464+
'--embed-file', 'hello1.wasm@/lib/libhello1.wasm',
6465+
'--embed-file', 'hello2.wasm@/usr/lib/libhello2.wasm',
6466+
'--embed-file', 'hello3.wasm@/libhello3.wasm',
6467+
'--embed-file', 'hello4.wasm@/usr/local/lib/libhello4.wasm',
6468+
'hello1.wasm', 'hello2.wasm', 'hello3.wasm', 'hello4.wasm', '-sNO_AUTOLOAD_DYLIBS',
64606469
'--pre-js', 'pre.js'])
64616470
out = self.run_js('main.js')
64626471
self.assertContained('Hello1', out)

0 commit comments

Comments
 (0)