Skip to content

Commit dd93c53

Browse files
committed
Make node::DLOpen use uv_dlopen
1 parent 2f22024 commit dd93c53

File tree

1 file changed

+53
-44
lines changed

1 file changed

+53
-44
lines changed

src/node.cc

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ typedef int mode_t;
6363
#endif
6464

6565
#ifdef __POSIX__
66-
# include <dlfcn.h> /* dlopen(), dlsym() */
6766
# include <pwd.h> /* getpwnam() */
6867
# include <grp.h> /* getgrnam() */
6968
#endif
@@ -1642,73 +1641,84 @@ Handle<Value> Kill(const Arguments& args) {
16421641
return Undefined();
16431642
}
16441643

1644+
#endif // __POSIX__
1645+
16451646

1646-
typedef void (*extInit)(Handle<Object> exports);
1647+
typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
16471648

16481649
// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
16491650
// objects.
16501651
Handle<Value> DLOpen(const v8::Arguments& args) {
1651-
node_module_struct compat_mod;
16521652
HandleScope scope;
1653+
char symbol[1024], *base, *pos;
1654+
uv_lib_t lib;
1655+
node_module_struct compat_mod;
1656+
uv_err_t err;
1657+
int r;
16531658

1654-
if (args.Length() < 2) return Undefined();
1659+
if (args.Length() < 2) {
1660+
return Undefined();
1661+
}
16551662

16561663
String::Utf8Value filename(args[0]->ToString()); // Cast
16571664
Local<Object> target = args[1]->ToObject(); // Cast
16581665

1659-
// Actually call dlopen().
1660-
// FIXME: This is a blocking function and should be called asynchronously!
1661-
// This function should be moved to file.cc and use libeio to make this
1662-
// system call.
1663-
void *handle = dlopen(*filename, RTLD_LAZY);
1664-
1665-
// Handle errors.
1666-
if (handle == NULL) {
1667-
Local<Value> exception = Exception::Error(String::New(dlerror()));
1668-
return ThrowException(exception);
1666+
err = uv_dlopen(*filename, &lib);
1667+
if (err.code != UV_OK) {
1668+
SetErrno(err);
1669+
return scope.Close(Integer::New(-1));
16691670
}
16701671

1671-
String::Utf8Value symbol(args[0]->ToString());
1672-
char *symstr = NULL;
1673-
{
1674-
char *sym = *symbol;
1675-
char *p = strrchr(sym, '/');
1676-
if (p != NULL) {
1677-
sym = p+1;
1678-
}
1672+
String::Utf8Value path(args[0]->ToString());
1673+
base = *path;
16791674

1680-
p = strrchr(sym, '.');
1681-
if (p != NULL) {
1682-
*p = '\0';
1675+
/* Find the shared library filename within the full path. */
1676+
#ifdef __POSIX__
1677+
pos = strrchr(base, '/');
1678+
if (pos != NULL) {
1679+
base = pos;
1680+
}
1681+
#else // Windows
1682+
for (;;) {
1683+
pos = strpbrk(base, "\\/:");
1684+
if (pos == NULL) {
1685+
break;
16831686
}
1687+
base = pos + 1;
1688+
}
1689+
#endif
1690+
1691+
/* Strip the .node extension. */
1692+
pos = strrchr(base, '.');
1693+
if (pos != NULL) {
1694+
*pos = '\0';
1695+
}
16841696

1685-
size_t slen = strlen(sym);
1686-
symstr = static_cast<char*>(calloc(1, slen + sizeof("_module") + 1));
1687-
memcpy(symstr, sym, slen);
1688-
memcpy(symstr+slen, "_module", sizeof("_module") + 1);
1697+
/* Add the `_module` suffix to the extension name. */
1698+
r = snprintf(symbol, sizeof symbol, "%s_module", base);
1699+
if (r <= 0 || r >= sizeof symbol) {
1700+
err.code = UV_ENOMEM;
1701+
SetErrno(err);
1702+
return scope.Close(Integer::New(-1));
16891703
}
16901704

16911705
// Get the init() function from the dynamically shared object.
1692-
node_module_struct *mod = static_cast<node_module_struct *>(dlsym(handle, symstr));
1693-
free(symstr);
1694-
symstr = NULL;
1706+
node_module_struct *mod;
1707+
err = uv_dlsym(lib, symbol, reinterpret_cast<void**>(&mod));
16951708

1696-
// Error out if not found.
1697-
if (mod == NULL) {
1709+
if (err.code != UV_OK) {
16981710
/* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
16991711
memset(&compat_mod, 0, sizeof compat_mod);
17001712

17011713
mod = &compat_mod;
17021714
mod->version = NODE_MODULE_VERSION;
17031715

1704-
void *init_handle = dlsym(handle, "init");
1705-
if (init_handle == NULL) {
1706-
dlclose(handle);
1707-
Local<Value> exception =
1708-
Exception::Error(String::New("No module symbol found in module."));
1709-
return ThrowException(exception);
1716+
err = uv_dlsym(lib, "init", reinterpret_cast<void**>(&mod->register_func));
1717+
if (err.code != UV_OK) {
1718+
uv_dlclose(lib);
1719+
SetErrno(err);
1720+
return scope.Close(Integer::New(-1));
17101721
}
1711-
mod->register_func = (extInit)(init_handle);
17121722
/* End Compatibility hack */
17131723
}
17141724

@@ -1726,8 +1736,6 @@ Handle<Value> DLOpen(const v8::Arguments& args) {
17261736
return Undefined();
17271737
}
17281738

1729-
#endif // __POSIX__
1730-
17311739

17321740
// TODO remove me before 0.4
17331741
Handle<Value> Compile(const Arguments& args) {
@@ -2161,10 +2169,11 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
21612169
NODE_SET_METHOD(process, "setgid", SetGid);
21622170
NODE_SET_METHOD(process, "getgid", GetGid);
21632171

2164-
NODE_SET_METHOD(process, "dlopen", DLOpen);
21652172
NODE_SET_METHOD(process, "_kill", Kill);
21662173
#endif // __POSIX__
21672174

2175+
NODE_SET_METHOD(process, "dlopen", DLOpen);
2176+
21682177
NODE_SET_METHOD(process, "uptime", Uptime);
21692178
NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
21702179
NODE_SET_METHOD(process, "uvCounters", UVCounters);

0 commit comments

Comments
 (0)