aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erl_nif.xml35
-rw-r--r--erts/emulator/beam/erl_nif.c11
-rw-r--r--erts/emulator/beam/io.c1
-rw-r--r--erts/emulator/test/sensitive_SUITE.erl3
-rw-r--r--erts/test/otp_SUITE.erl38
5 files changed, 58 insertions, 30 deletions
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 8daa67aa87..5fc6508aad 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -136,9 +136,7 @@ ok
then retrieved by calling <seealso marker="#enif_priv_data">enif_priv_data</seealso>.</p>
<p>There is no way to explicitly unload a NIF library. A library will be
automatically unloaded when the module code that it belongs to is purged
- by the code server. A NIF library will also be unloaded if it is replaced
- by another version of the library by a second call to
- <c>erlang:load_nif/2</c> from the same module code.</p>
+ by the code server.</p>
</description>
<section>
<title>FUNCTIONALITY</title>
@@ -308,21 +306,9 @@ ok
initialization is needed.</p>
</item>
- <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag>
- <item><p><c>reload</c> is called when the NIF library is loaded
- and there is already a previously loaded library for this
- module code.</p>
- <p>Works the same as <c>load</c>. The only difference is that
- <c>*priv_data</c> already contains the value set by the
- previous call to <c>load</c> or <c>reload</c>.</p>
- <p>The library will fail to load if <c>reload</c> returns
- anything other than 0 or if <c>reload</c> is NULL.</p>
- </item>
-
<tag><marker id="upgrade"/>int (*upgrade)(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</tag>
<item><p><c>upgrade</c> is called when the NIF library is loaded
- and there is no previously loaded library for this module
- code, BUT there is old code of this module with a loaded NIF library.</p>
+ and there is old code of this module with a loaded NIF library.</p>
<p>Works the same as <c>load</c>. The only difference is that
<c>*old_priv_data</c> already contains the value set by the
last call to <c>load</c> or <c>reload</c> for the old module
@@ -339,6 +325,23 @@ ok
called for a replaced library as a consequence of <c>reload</c>.</p>
</item>
+ <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag>
+ <note><p>The reload mechanism is <em>deprecated</em>. It was only intended
+ as a development feature. Do not use it as an upgrade method for
+ live production systems. It might be removed in future releases. Be sure
+ to pass <c>reload</c> as <c>NULL</c> to <seealso marker="#ERL_NIF_INIT">ERL_NIF_INIT</seealso>
+ to disable it when not used.</p>
+ </note>
+ <item><p><c>reload</c> is called when the NIF library is loaded
+ and there is already a previously loaded library for this
+ module code.</p>
+ <p>Works the same as <c>load</c>. The only difference is that
+ <c>*priv_data</c> already contains the value set by the
+ previous call to <c>load</c> or <c>reload</c>.</p>
+ <p>The library will fail to load if <c>reload</c> returns
+ anything other than 0 or if <c>reload</c> is NULL.</p>
+ </item>
+
</taglist>
</section>
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 143f631f58..58a09986d2 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1507,6 +1507,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
Eterm ret = am_ok;
int veto;
struct erl_module_nif* lib = NULL;
+ int reload_warning = 0;
len = list_length(BIF_ARG_1);
if (len < 0) {
@@ -1646,6 +1647,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
else {
mod->nif->entry = NULL; /* to prevent 'unload' callback */
erts_unload_nif(mod->nif);
+ reload_warning = 1;
}
}
else {
@@ -1714,6 +1716,15 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
erts_smp_thr_progress_unblock();
erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_free(ERTS_ALC_T_TMP, lib_name);
+
+ if (reload_warning) {
+ erts_dsprintf_buf_t* dsbufp = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbufp,
+ "Repeated calls to erlang:load_nif from module '%T'.\n\n"
+ "The NIF reload mechanism is deprecated and must not "
+ "be used in production systems.\n", mod_atom);
+ erts_send_warning_to_logger(BIF_P->group_leader, dsbufp);
+ }
BIF_RET(ret);
}
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index c2cc03509e..759621d3c2 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -644,7 +644,6 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
name, opts);
erts_unblock_fpe(fpe_was_unmasked);
port->caller = NIL;
- erts_unblock_fpe(fpe_was_unmasked);
if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) {
trace_sched_ports_where(port, am_out, am_start);
}
diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl
index 634df367ca..e073eab596 100644
--- a/erts/emulator/test/sensitive_SUITE.erl
+++ b/erts/emulator/test/sensitive_SUITE.erl
@@ -160,8 +160,7 @@ recv_trace(Config) when is_list(Config) ->
?line {messages,Messages} = process_info(Tracer, messages),
[{trace,Parent,'receive',a},
{trace,Parent,'receive',{trace_delivered,_,_}},
- {trace,Parent,'receive',c},
- {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages,
+ {trace,Parent,'receive',c}|_] = Messages,
?line unlink(Tracer), exit(Tracer, kill),
?line unlink(Sender), exit(Sender, kill),
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index d61fbbddcf..79cd91221f 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -94,15 +94,16 @@ undefined_functions(Config) when is_list(Config) ->
case Undef of
[] -> ok;
_ ->
+ Fd = open_log(Config, "undefined_functions"),
foreach(fun ({MFA1,MFA2}) ->
io:format("~s calls undefined ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)]),
+ io:format(Fd, "~s ~s\n",
[format_mfa(MFA1),format_mfa(MFA2)])
end, Undef),
+ close_log(Fd),
?line ?t:fail({length(Undef),undefined_functions_in_otp})
-
- end,
-
- ok.
+ end.
hipe_filter(Undef) ->
case erlang:system_info(hipe_architecture) of
@@ -211,7 +212,10 @@ deprecated_not_in_obsolete(Config) when is_list(Config) ->
_ ->
io:put_chars("The following functions have -deprecated() attributes,\n"
"but are not listed in otp_internal:obsolete/3.\n"),
- ?line print_mfas(L),
+ ?line print_mfas(group_leader(), L),
+ Fd = open_log(Config, "deprecated_not_obsolete"),
+ print_mfas(Fd, L),
+ close_log(Fd),
?line ?t:fail({length(L),deprecated_but_not_obsolete})
end.
@@ -232,11 +236,13 @@ obsolete_but_not_deprecated(Config) when is_list(Config) ->
io:put_chars("The following functions are listed "
"in otp_internal:obsolete/3,\n"
"but don't have -deprecated() attributes.\n"),
- ?line print_mfas(L),
+ ?line print_mfas(group_leader(), L),
+ Fd = open_log(Config, "obsolete_not_deprecated"),
+ print_mfas(Fd, L),
+ close_log(Fd),
?line ?t:fail({length(L),obsolete_but_not_deprecated})
end.
-
call_to_deprecated(Config) when is_list(Config) ->
Server = ?config(xref_server, Config),
?line {ok,DeprecatedCalls} = xref:q(Server, "strict(E || DF)"),
@@ -302,10 +308,20 @@ strong_components(Config) when is_list(Config) ->
%%%
-print_mfas([MFA|T]) ->
- io:format("~s\n", [format_mfa(MFA)]),
- print_mfas(T);
-print_mfas([]) -> ok.
+print_mfas(Fd, [MFA|T]) ->
+ io:format(Fd, "~s\n", [format_mfa(MFA)]),
+ print_mfas(Fd, T);
+print_mfas(_, []) -> ok.
format_mfa({M,F,A}) ->
lists:flatten(io_lib:format("~s:~s/~p", [M,F,A])).
+
+open_log(Config, Name) ->
+ PrivDir = ?config(priv_dir, Config),
+ RunDir = filename:dirname(filename:dirname(PrivDir)),
+ Path = filename:join(RunDir, "system_"++Name++".log"),
+ {ok,Fd} = file:open(Path, [write]),
+ Fd.
+
+close_log(Fd) ->
+ ok = file:close(Fd).