- this is just PoC code. not meant to represent a desired api. just enough to get things to work on linux.
- this technique will only work on linux but there are possibly other techniques that would work on macos and windows. more to follow.
- it will only work if
procfs
is mounted.dlopen
is called with the path/proc/self/${fd}
with the fd frommemfd_create
- you will still have to deal with the issue of any external dependencies of the node addons you want to embed in the SEA
- if static linking the addons against those dependencies is an option you can do that
- it would be much nicer if we could static link addons and their dependencies into a statically linked SEA binary, but this would require re-linking node
-
go here https://gitpod.io#snapshot/69703ffb-148d-41ef-a453-71ee27068dde
-
open terminal in the IDE
-
run the demo
cd sea_legs
./demo
- use latest node as the changes are based on main
nvm install v23.6.1
rebuild the addon and run the demo
cd sea_legs
node-gyp rebuild
./sea.sh
./demo
if you want to verify the library is not being loaded from disk you can install strace
sudo apt install -y strace
and run the demo to see the files it opens
cd sea_legs
strace -e openat ./demo
you should see output like this
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ssl/openssl.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/version_signature", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/sys/fs/cgroup/user/memory.max", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/sys/fs/cgroup/user/memory.high", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/meminfo", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY) = 21
openat(AT_FDCWD, "/workspace/node/sea_legs/demo", O_RDONLY) = 21
openat(AT_FDCWD, "/proc/self/fd/21", O_RDONLY|O_CLOEXEC) = 22
openat(AT_FDCWD, "/dev/pts/1", O_RDWR|O_NOCTTY|O_CLOEXEC) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/null", O_RDONLY|O_CLOEXEC) = 22
openat(AT_FDCWD, "/dev/pts/1", O_RDWR|O_NOCTTY|O_CLOEXEC) = -1 EACCES (Permission denied)
1806
+++ exited with 0 +++
as opposed to what you would see with node.js
cd sea_legs
strace -e openat ../out/Release/node demo.js
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ssl/openssl.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/version_signature", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/sys/fs/cgroup/user/memory.max", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/sys/fs/cgroup/user/memory.high", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/meminfo", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY) = 21
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY) = 21
openat(AT_FDCWD, "/workspace/node/out/Release/node", O_RDONLY) = 21
openat(AT_FDCWD, "/workspace/node/sea_legs/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/sea_legs/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/sea_legs/demo.js", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/workspace/node/sea_legs/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/package.json", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/workspace/node/sea_legs/build/Release/demo.node", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/dev/pts/1", O_RDWR|O_NOCTTY|O_CLOEXEC) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/dev/null", O_RDONLY|O_CLOEXEC) = 21
openat(AT_FDCWD, "/dev/pts/1", O_RDWR|O_NOCTTY|O_CLOEXEC) = -1 EACCES (Permission denied)
1833
+++ exited with 0 +++
info on how to do it on windoze