Skip to content

Commit a0d8c34

Browse files
committed
Rename label to filename argument
1 parent 8d459f0 commit a0d8c34

3 files changed

Lines changed: 53 additions & 22 deletions

File tree

erts/emulator/beam/erl_nif.c

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@
6868
#endif
6969
#include "jit/beam_asm.h"
7070
#include "erl_global_literals.h"
71+
7172
#include "erl_iolist.h"
73+
#include "erl_atom_table.h"
7274

7375
#include <limits.h>
7476
#include <stddef.h> /* offsetof */
@@ -4884,38 +4886,41 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
48844886
/*
48854887
* Accept either:
48864888
* Filename::string()|binary() -- load from file (existing behaviour)
4887-
* #{memory := NifSO} -- load from memory, auto-generated label
4888-
* #{memory := NifSO, label := Filename} -- load from memory with explicit label
4889+
* #{filename := string()|binary()} -- load from file (map form, no memory)
4890+
* #{memory := NifSO} -- load from memory, auto-generated filename
4891+
* #{memory := NifSO, filename := Filename} -- load from memory with explicit filename
4892+
*
4893+
* If the map contains only 'filename', it falls back to the string|binary filename implementation.
48894894
*/
48904895
if (is_map(filename)) {
4891-
const Eterm *mem_val = erts_maps_get(am_memory, filename);
4892-
const Eterm *lbl_val = erts_maps_get(am_label, filename);
4893-
if (mem_val == NULL) {
4896+
const Eterm *fnm_val = erts_maps_get(am_filename, filename);
4897+
const Eterm *mem_val = erts_maps_get(am_memory, filename);
4898+
if (fnm_val == NULL && mem_val == NULL) {
48944899
return load_nif_error(c_p, "bad_lib",
4895-
"load_nif/2: map argument must contain a 'memory' key");
4900+
"load_nif/2: map argument must contain a 'memory' or 'filename'key");
48964901
}
4897-
if (!is_bitstring(*mem_val) || TAIL_BITS(bitstring_size(*mem_val)) != 0) {
4898-
return load_nif_error(c_p, "bad_lib",
4899-
"load_nif/2: 'memory' value must be a binary");
4902+
if (mem_val) {
4903+
if (!is_bitstring(*mem_val) || TAIL_BITS(bitstring_size(*mem_val)) != 0) {
4904+
return load_nif_error(c_p, "bad_lib",
4905+
"load_nif/2: 'memory' value must be a binary");
4906+
}
4907+
nif_binary = *mem_val;
4908+
load_from_mem = 1;
49004909
}
4901-
nif_binary = *mem_val;
4902-
load_from_mem = 1;
4903-
if (lbl_val != NULL) {
4904-
filename = *lbl_val; /* fall through to filename decoding for label */
4910+
if (fnm_val) {
4911+
filename = *fnm_val; /* fall through to filename decoding from argument */
49054912
} else {
49064913
lib_name = NULL; /* anonymous: erts_dlopen_mem will generate a name */
49074914
goto after_lib_name;
49084915
}
49094916
}
4910-
49114917
lib_name = erts_convert_filename_to_encoding(filename, NULL, 0,
49124918
ERTS_ALC_T_TMP, 1, 0, encoding,
49134919
NULL, 0);
4914-
if (!lib_name) {
4920+
if (!lib_name)
49154921
return THE_NON_VALUE;
4916-
}
4917-
after_lib_name:;
49184922

4923+
after_lib_name:
49194924
/* Find calling module */
49204925
caller = erts_find_function_from_pc(I);
49214926
ASSERT(caller != NULL);
@@ -4947,7 +4952,7 @@ after_lib_name:;
49474952
this_mi = module_p->on_load;
49484953
}
49494954

4950-
/* If the caller passed #{memory => NifSO::binary(), label => Filename},
4955+
/* If the caller passed #{memory => NifSO::binary(), filename => Filename},
49514956
* open the shared object from memory now so that `handle` is ready for
49524957
* the common else-if chain below (which runs
49534958
* erts_sys_ddll_load_nif_init / call_nif_init, version checks, and

erts/emulator/test/nif_SUITE.erl

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ run_load_nif_from_mem(Config) ->
383383
SoPath = filename:join(Data, "nif_mod.1.so"),
384384
{ok, SoBin} = file:read_file(SoPath),
385385

386-
%% --- happy path: map with label ---
386+
%% --- happy path: map with filename ---
387387
ok = nif_mod:load_nif_lib_from_mem(Config, 1, SoBin),
388388
1 = nif_mod:lib_version(),
389389

@@ -399,7 +399,6 @@ run_load_nif_from_mem(Config) ->
399399
true = erlang:purge_module(nif_mod),
400400
receive unloaded -> ok after 1000 -> ok end,
401401

402-
%% --- error: label longer than PATH_MAX-9 ---
403402
{module, nif_mod} = erlang:load_module(nif_mod, ModBin),
404403
LongPath = lists:duplicate(4096-9, $x),
405404
{error, {load_failed, _}} = nif_mod:load_nif_mem_path(LongPath, SoBin),
@@ -415,6 +414,30 @@ run_load_nif_from_mem(Config) ->
415414
true = erlang:purge_module(nif_mod),
416415
receive unloaded -> ok after 1000 -> ok end,
417416

417+
%% --- error: both keys present but filename is not string/binary ---
418+
{module, nif_mod} = erlang:load_module(nif_mod, ModBin),
419+
Map1 = #{memory => SoBin, filename => 123},
420+
{error, {bad_lib, _}} = erlang:load_nif(Map1, []),
421+
true = erlang:delete_module(nif_mod),
422+
true = erlang:purge_module(nif_mod),
423+
receive unloaded -> ok after 1000 -> ok end,
424+
425+
%% --- error: map with neither memory nor filename ---
426+
{module, nif_mod} = erlang:load_module(nif_mod, ModBin),
427+
Map2 = #{foo => bar},
428+
{error, {bad_lib, _}} = erlang:load_nif(Map2, []),
429+
true = erlang:delete_module(nif_mod),
430+
true = erlang:purge_module(nif_mod),
431+
receive unloaded -> ok after 1000 -> ok end,
432+
433+
%% --- error: map with only filename key and non-string/binary value ---
434+
{module, nif_mod} = erlang:load_module(nif_mod, ModBin),
435+
Map3 = #{filename => 123},
436+
{error, {bad_lib, _}} = erlang:load_nif(Map3, []),
437+
true = erlang:delete_module(nif_mod),
438+
true = erlang:purge_module(nif_mod),
439+
receive unloaded -> ok after 1000 -> ok end,
440+
418441
ok.
419442

420443
%% Test old reload feature now always fails

erts/preloaded/src/erlang.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7538,12 +7538,14 @@ forms:
75387538
on disc when an upgrade of the NIF is done. If the name is the same, but the
75397539
contents differ, the old library may be loaded instead.
75407540
7541+
- **`#{filename := string()|binary()}`** - Same as above.
7542+
75417543
- **`#{memory := NifSO}`** - Load the NIF library directly from the in-memory
75427544
binary `NifSO` (raw bytes of the shared-object file) without a label. An
75437545
anonymous name is auto-generated for the shared-memory region. Only supported
75447546
on Unix platforms that provide `memfd_create(2)` or POSIX shared memory.
75457547
7546-
- **`#{memory := NifSO, label := Filename}`** - Same as above, but `Filename`
7548+
- **`#{memory := NifSO, filename := Filename}`** - Same as above, but `Filename`
75477549
(a `string()` or `binary()`) is used as the label for the shared-memory
75487550
region and in error messages. `Filename` must be shorter than `PATH_MAX - 9`
75497551
characters (to allow for the `/dev/shm/` prefix used internally).
@@ -7635,9 +7637,10 @@ target OS/hardware platform.
76357637
-spec load_nif(Path, LoadInfo) -> ok | Error when
76367638
Path :: string() |
76377639
binary() |
7640+
#{filename := Filename :: string() | binary()} |
76387641
#{memory := NifSO :: binary()} |
76397642
#{memory := NifSO :: binary(),
7640-
label := Filename :: string() | binary()},
7643+
filename := Filename :: string() | binary()},
76417644
LoadInfo :: term(),
76427645
Error :: {error, {Reason, Text :: string()}},
76437646
Reason :: load_failed | bad_lib | load | reload | upgrade | old_code.

0 commit comments

Comments
 (0)