Commit 67cf2fa
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
- erts
- emulator
- beam
- test
- nif_SUITE_data
- preloaded/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
213 | 213 | | |
214 | 214 | | |
215 | 215 | | |
| 216 | + | |
216 | 217 | | |
217 | 218 | | |
218 | 219 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| 314 | + | |
314 | 315 | | |
315 | 316 | | |
316 | 317 | | |
| |||
0 commit comments