Skip to content

Commit 67cf2fa

Browse files
committed
erts: Allow erlang:load_nif/2 to load a NIF from an in-memory binary
Add support for passing `#{memory => NifSO::binary(), filename => string():binary()}` as the first argument to erlang:load_nif/2. When a map is given with the 'memory' key/value present, the NIF shared object is loaded directly from the binary image in memory instead of from the file system. If the map only contains the 'filename' key/value it'll revert to the default behavior of loading the SO from file. This addition is needed so that escripts can package SO dependencies inside and be distributed as a single executable. Implementation -------------- * erts_dlopen_mem() — new static helper in erl_nif.c (Linux/POSIX only). On Linux >= 3.17 it uses memfd_create(2) to create an anonymous in-memory file, writes the SO image into it, and calls dlopen(3) via /proc/self/fd/<fd>. On older Linux kernels and other POSIX systems it falls back to shm_open(3) + /dev/shm/<name>. The implementation is derived from the https://github.com/saleyn/memfd_create proof of concept. * erts_load_nif() — extended argument parsing: - Plain filename() continues to work unchanged. - #{memory => Binary, filename => Filename} map: Binary is extracted via erts_get_aligned_binary_bytes(), passed to erts_dlopen_mem(), and the resulting dlopen handle is used directly. The Filename string serves only as a label inside the memory-backed file descriptor. - The open-from-memory step is performed before the existing else-if validation chain (version checks, module-name check, create_lib) so both code paths share the same validation and bookkeeping. - erts_sys_ddll_open() is skipped (via !load_from_mem guard) when a handle was already obtained from memory. * The feature is guarded by #if defined(HAVE_DLOPEN) && defined(__unix__). On unsupported platforms load_nif/2 returns {error,{load_failed,…}}. Testing ------- * nif_SUITE: new test case load_nif_from_mem - Happy path: reads nif_mod.1.so into a binary, calls erlang:load_nif(#{filename => Path, memory => Binary}, []) via nif_mod:load_nif_lib_from_mem/3, and asserts lib_version() == 1. - Error path: non-binary second element returns {error,{bad_lib,_}}. * nif_mod.erl: new exported helper load_nif_lib_from_mem/3 so that the load_nif call site lives inside the NIF module (required by the BIF).
1 parent b40d9ef commit 67cf2fa

6 files changed

Lines changed: 452 additions & 46 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ JAVADOC-GENERATED
213213
/erts/emulator/test/*_native_SUITE.erl
214214
/erts/emulator/test/*_SUITE_data/Makefile
215215
/erts/emulator/test/*_stripped_types_SUITE.erl
216+
/erts/emulator/test/nif_SUITE_data/*.so
216217
/erts/test/install_SUITE_data/install_bin
217218
/erts/test/autoimport_SUITE_data/erlang.xml
218219
/erts/emulator/make_test_dir/

erts/emulator/beam/atom.names

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ atom extra
311311
atom false
312312
atom fcgi
313313
atom fd
314+
atom filename
314315
atom first
315316
atom firstline
316317
atom flags

0 commit comments

Comments
 (0)