diff options
author | Sverker Eriksson <[email protected]> | 2019-03-21 21:05:42 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2019-03-21 21:05:42 +0100 |
commit | bc3de715d1aaf6604cd8bde43900f22a631ce548 (patch) | |
tree | 4374576ce4d5b785fb03108b5aa3ba203f303332 /erts/emulator/test | |
parent | d015f4819d14694fe81b0ddb5935d14c80898ccc (diff) | |
parent | 9cce1357c3a0d3e13c57a0d9baaeccd249efe136 (diff) | |
download | otp-bc3de715d1aaf6604cd8bde43900f22a631ce548.tar.gz otp-bc3de715d1aaf6604cd8bde43900f22a631ce548.tar.bz2 otp-bc3de715d1aaf6604cd8bde43900f22a631ce548.zip |
Merge 'sverker/master/enif_whereis_pid-dirty-dtor/OTP-15694'
* sverker/master/enif_whereis_pid-dirty-dtor:
erts: Add test of enif_whereis* from resource destructor
erts: Simplify nif_SUITE:nif_whereis* tests
erts: Schedule resource destructors always
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 44 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 176 |
2 files changed, 118 insertions, 102 deletions
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 62b7f77a52..b824daea67 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -28,6 +28,7 @@ -include_lib("stdlib/include/assert.hrl"). -export([all/0, suite/0, groups/0, + init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, basic/1, reload_error/1, upgrade/1, heap_frag/1, @@ -109,6 +110,14 @@ all() -> pid, nif_term_type]. +init_per_suite(Config) -> + erts_debug:set_internal_state(available_internal_state, true), + Config. + +end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false), + ok. + groups() -> [{G, [], api_repeaters()} || G <- api_groups()] ++ @@ -118,7 +127,6 @@ groups() -> monitor_process_d, demonitor_process]}]. - api_groups() -> [api_latest, api_2_4, api_2_0]. api_repeaters() -> [upgrade, resource_takeover, t_on_load]. @@ -1760,6 +1768,7 @@ read_resource(Type, {Holder,Id}) -> forget_resource({Holder,Id}) -> Holder ! {self(), forget, Id}, {Holder, forget_ok, Id} = receive_any(), + erts_debug:set_internal_state(wait, aux_work), ok. @@ -3105,22 +3114,31 @@ nif_whereis_threaded(Config) when is_list(Config) -> RegName = nif_whereis_test_threaded, undefined = erlang:whereis(RegName), - Ref = make_ref(), - {Pid, Mon} = spawn_monitor(?MODULE, nif_whereis_proxy, [Ref]), - true = register(RegName, Pid), + Self = self(), + true = register(RegName, Self), - {ok, ProcThr} = whereis_thd_lookup(pid, RegName), - {ok, Pid} = whereis_thd_result(ProcThr), + {ok, ProcThr} = whereis_thd_lookup(pid, RegName, "dtor to proc"), + {ok, Self} = whereis_thd_result(ProcThr), - Pid ! {Ref, quit}, - ok = receive {'DOWN', Mon, process, Pid, normal} -> ok end, + nif_whereis_threaded_2(RegName). + +nif_whereis_threaded_2(RegName) -> + erlang:garbage_collect(), + "dtor to proc" = receive_any(1000), + true = unregister(RegName), Port = open_port({spawn, echo_drv}, [eof]), true = register(RegName, Port), - {ok, PortThr} = whereis_thd_lookup(port, RegName), + {ok, PortThr} = whereis_thd_lookup(port, RegName, "dtor to port"), {ok, Port} = whereis_thd_result(PortThr), + nif_whereis_threaded_3(Port). + +nif_whereis_threaded_3(Port) -> + erlang:garbage_collect(), + {Port, {data, "dtor to port"}} = receive_any(1000), + port_close(Port), ok. @@ -3435,6 +3453,10 @@ nif_term_type(Config) -> ok. +last_resource_dtor_call() -> + erts_debug:set_internal_state(wait, aux_work), + last_resource_dtor_call_nif(). + id(I) -> I. %% The NIFs: @@ -3462,7 +3484,7 @@ make_resource(_) -> ?nif_stub. get_resource(_,_) -> ?nif_stub. release_resource(_) -> ?nif_stub. release_resource_from_thread(_) -> ?nif_stub. -last_resource_dtor_call() -> ?nif_stub. +last_resource_dtor_call_nif() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. check_is_exception() -> ?nif_stub. @@ -3522,7 +3544,7 @@ ioq_nif(_,_,_,_) -> ?nif_stub. %% whereis whereis_send(_Type,_Name,_Msg) -> ?nif_stub. whereis_term(_Type,_Name) -> ?nif_stub. -whereis_thd_lookup(_Type,_Name) -> ?nif_stub. +whereis_thd_lookup(_Type,_Name, _Msg) -> ?nif_stub. whereis_thd_result(_Thd) -> ?nif_stub. %% maps diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 1906384af4..ff47cfe500 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -27,6 +27,7 @@ #ifndef __WIN32__ #include <unistd.h> #include <fcntl.h> +#include <sys/uio.h> #endif #include "nif_mod.h" @@ -707,28 +708,23 @@ static ERL_NIF_TERM tuple_2_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM is_identical(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 2) { - return enif_make_badarg(env); - } + assert(argc == 2); return enif_make_atom(env, (enif_is_identical(argv[0],argv[1]) ? "true" : "false")); } static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 2) { - return enif_make_badarg(env); - } + assert(argc == 2); return enif_make_int(env, enif_compare(argv[0],argv[1])); } static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 3) { - return enif_make_badarg(env); - } - ErlNifHash type; + ErlNifUInt64 salt; + + assert(argc == 3); if (enif_is_identical(argv[0], enif_make_atom(env, "internal"))) { type = ERL_NIF_INTERNAL_HASH; } @@ -739,7 +735,6 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] return enif_make_badarg(env); } - ErlNifUInt64 salt; if (! enif_get_uint64(env, argv[2], &salt)) { return enif_make_badarg(env); } @@ -866,7 +861,7 @@ static ERL_NIF_TERM iolist_2_bin(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return enif_make_binary(env,&obin); } -static ERL_NIF_TERM last_resource_dtor_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM last_resource_dtor_call_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; if (resource_dtor_last != NULL) { @@ -1010,6 +1005,7 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER static void* threaded_release_resource(void* resource) { enif_release_resource(resource); + return NULL; } static ERL_NIF_TERM release_resource_from_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -1201,7 +1197,6 @@ static void fill(void* dst, unsigned bytes, int seed) enum { /* results */ WHEREIS_SUCCESS, - WHEREIS_ERROR_TYPE, WHEREIS_ERROR_LOOKUP, WHEREIS_ERROR_SEND, /* types */ @@ -1221,6 +1216,8 @@ typedef struct { whereis_term_data_t res; ErlNifTid tid; int type; + int rc; + ERL_NIF_TERM dtor_msg; } whereis_thread_resource_t; static whereis_thread_resource_t* whereis_thread_resource_create(void) @@ -1233,21 +1230,35 @@ static whereis_thread_resource_t* whereis_thread_resource_create(void) return rp; } +static int whereis_lookup_internal(ErlNifEnv*, int type, ERL_NIF_TERM name, + whereis_term_data_t* out); +static int whereis_send_internal(ErlNifEnv*, int type, whereis_term_data_t* to, + ERL_NIF_TERM msg); + + static void whereis_thread_resource_dtor(ErlNifEnv* env, void* obj) { whereis_thread_resource_t* rp = (whereis_thread_resource_t*) obj; + whereis_term_data_t to; + + if (whereis_lookup_internal(env, rp->type, rp->name, &to) + == WHEREIS_SUCCESS) { + whereis_send_internal(env, rp->type, &to, rp->dtor_msg); + } enif_free_env(rp->env); } -static int whereis_type(ERL_NIF_TERM type) +static int whereis_type(ERL_NIF_TERM type_term, int* type_p) { - if (enif_is_identical(type, atom_pid)) - return WHEREIS_LOOKUP_PID; - - if (enif_is_identical(type, atom_port)) - return WHEREIS_LOOKUP_PORT; - - return WHEREIS_ERROR_TYPE; + if (enif_is_identical(type_term, atom_pid)) { + *type_p = WHEREIS_LOOKUP_PID; + return 1; + } + if (enif_is_identical(type_term, atom_port)) { + *type_p = WHEREIS_LOOKUP_PORT; + return 1; + } + return 0; } static int whereis_lookup_internal( @@ -1261,7 +1272,7 @@ static int whereis_lookup_internal( return enif_whereis_port(env, name, & out->port) ? WHEREIS_SUCCESS : WHEREIS_ERROR_LOOKUP; - return WHEREIS_ERROR_TYPE; + abort(); } static int whereis_send_internal( @@ -1275,23 +1286,20 @@ static int whereis_send_internal( return enif_port_command(env, & to->port, NULL, msg) ? WHEREIS_SUCCESS : WHEREIS_ERROR_SEND; - return WHEREIS_ERROR_TYPE; + abort(); } -static int whereis_resolved_term( - ErlNifEnv* env, int type, whereis_term_data_t* res, ERL_NIF_TERM* out) +static ERL_NIF_TERM whereis_resolved_term( + ErlNifEnv* env, int type, whereis_term_data_t* res) { switch (type) { case WHEREIS_LOOKUP_PID: - *out = enif_make_pid(env, & res->pid); - break; + return enif_make_pid(env, &res->pid); case WHEREIS_LOOKUP_PORT: - *out = enif_make_port(env, & res->port); - break; + return enif_make_port(env, &res->port); default: - return WHEREIS_ERROR_TYPE; + abort(); } - return WHEREIS_SUCCESS; } static ERL_NIF_TERM whereis_result_term(ErlNifEnv* env, int result) @@ -1307,9 +1315,6 @@ static ERL_NIF_TERM whereis_result_term(ErlNifEnv* env, int result) case WHEREIS_ERROR_SEND: err = atom_send; break; - case WHEREIS_ERROR_TYPE: - err = atom_badarg; - break; default: err = enif_make_int(env, -result); break; @@ -1320,14 +1325,10 @@ static ERL_NIF_TERM whereis_result_term(ErlNifEnv* env, int result) static void* whereis_lookup_thread(void* arg) { whereis_thread_resource_t* rp = (whereis_thread_resource_t*) arg; - int rc; - /* enif_whereis_xxx should work with allocated or null env */ - rc = whereis_lookup_internal( - ((rp->type == WHEREIS_LOOKUP_PID) ? NULL : rp->env), - rp->type, rp->name, & rp->res); + rp->rc = whereis_lookup_internal(NULL, rp->type, rp->name, &rp->res); - return (((char*) NULL) + rc); + return NULL; } /* whereis_term(Type, Name) -> pid() | port() | false */ @@ -1335,20 +1336,16 @@ static ERL_NIF_TERM whereis_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { whereis_term_data_t res; - ERL_NIF_TERM ret; int type, rc; - if (argc != 2) /* allow non-atom name for testing */ - return enif_make_badarg(env); - - if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + assert(argc == 2); + if (!whereis_type(argv[0], &type)) return enif_make_badarg(env); rc = whereis_lookup_internal(env, type, argv[1], & res); - if (rc == WHEREIS_SUCCESS) { - rc = whereis_resolved_term(env, type, & res, & ret); - } - return (rc == WHEREIS_SUCCESS) ? ret : atom_false; + return (rc == WHEREIS_SUCCESS ? + whereis_resolved_term(env, type, &res) : + atom_false); } /* whereis_send(Type, Name, Message) -> ok | {error, Reason} */ @@ -1358,10 +1355,11 @@ whereis_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) whereis_term_data_t to; int type, rc; - if (argc != 3 || !enif_is_atom(env, argv[1])) + assert(argc == 3); + if (!enif_is_atom(env, argv[1])) return enif_make_badarg(env); - if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + if (!whereis_type(argv[0], &type)) return enif_make_badarg(env); rc = whereis_lookup_internal(env, type, argv[1], & to); @@ -1371,33 +1369,35 @@ whereis_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return whereis_result_term(env, rc); } -/* whereis_thd_lookup(Type, Name) -> {ok, Resource} | {error, SysErrno} */ +/* whereis_thd_lookup(Type, Name, DtorMsg) -> {ok, Resource} | {error, SysErrno} */ static ERL_NIF_TERM whereis_thd_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { whereis_thread_resource_t* rp; int type, rc; + ERL_NIF_TERM ret; - if (argc != 2 || !enif_is_atom(env, argv[1])) + assert(argc == 3); + if (!enif_is_atom(env, argv[1])) return enif_make_badarg(env); - if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + if (!whereis_type(argv[0], &type)) return enif_make_badarg(env); rp = whereis_thread_resource_create(); rp->type = type; rp->name = enif_make_copy(rp->env, argv[1]); + rp->dtor_msg = enif_make_copy(rp->env, argv[2]); rc = enif_thread_create( "nif_SUITE:whereis_thd", & rp->tid, whereis_lookup_thread, rp, NULL); - if (rc == 0) { - return enif_make_tuple2(env, atom_ok, enif_make_resource(env, rp)); - } - else { - enif_release_resource(rp); - return enif_make_tuple2(env, atom_error, enif_make_int(env, rc)); - } + if (rc == 0) + ret = enif_make_tuple2(env, atom_ok, enif_make_resource(env, rp)); + else + ret = enif_make_tuple2(env, atom_error, enif_make_int(env, rc)); + enif_release_resource(rp); + return ret; } /* whereis_thd_result(Resource) -> {ok, pid() | port()} | {error, ErrNum} */ @@ -1406,24 +1406,22 @@ whereis_thd_result(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { whereis_thread_resource_t* rp; ERL_NIF_TERM ret; - char* thdret; /* so we can keep compilers happy converting to int */ - int rc; + int join_rc; - if (argc != 1 - || !enif_get_resource(env, argv[0], whereis_resource_type, (void**) & rp)) + assert(argc == 1); + if (!enif_get_resource(env, argv[0], whereis_resource_type, (void**) & rp)) return enif_make_badarg(env); - if ((rc = enif_thread_join(rp->tid, (void**) & thdret)) != 0) - return enif_make_tuple2(env, atom_error, enif_make_int(env, rc)); + if ((join_rc = enif_thread_join(rp->tid, NULL)) != 0) + return enif_make_tuple2(env, atom_error, enif_make_int(env, join_rc)); - rc = (int)(thdret - ((char*) NULL)); - if (rc == WHEREIS_SUCCESS) { - rc = whereis_resolved_term(env, rp->type, & rp->res, & ret); + if (rp->rc == WHEREIS_SUCCESS) { + ret = enif_make_tuple2(env, atom_ok, + whereis_resolved_term(env, rp->type, &rp->res)); } - ret = (rc == WHEREIS_SUCCESS) - ? enif_make_tuple2(env, atom_ok, ret) : whereis_result_term(env, rc); + else + ret = whereis_result_term(env, rp->rc); - enif_release_resource(rp); return ret; } @@ -2007,8 +2005,7 @@ static ERL_NIF_TERM nif_sched1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv static ERL_NIF_TERM call_nif_schedule(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM result; - if (argc != 2) - return enif_make_atom(env, "false"); + assert(argc == 2); result = enif_schedule_nif(env, "nif_sched1", 0, nif_sched1, argc, argv); assert(!enif_is_exception(env, result)); return result; @@ -2155,7 +2152,8 @@ static ERL_NIF_TERM maps_from_list_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ERL_NIF_TERM result, cell; unsigned count; - if (argc != 1 || !enif_get_list_length(env, argv[0], &count)) { + assert(argc == 1); + if (!enif_get_list_length(env, argv[0], &count)) { return enif_make_badarg(env); } @@ -2202,7 +2200,8 @@ static ERL_NIF_TERM sorted_list_from_maps_nif(ErlNifEnv* env, int argc, const ER ErlNifMapIterator iter_b; int cnt, next_ret, prev_ret; - if (argc != 1 && !enif_is_map(env, map)) + assert(argc == 1); + if (!enif_is_map(env, map)) return enif_make_int(env, __LINE__); if(!enif_map_iterator_create(env, map, &iter_f, ERL_NIF_MAP_ITERATOR_FIRST)) @@ -2263,9 +2262,7 @@ static ERL_NIF_TERM monotonic_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM { ErlNifTimeUnit time_unit; - if (argc != 1) - return atom_false; - + assert(argc == 1); if (enif_compare(argv[0], atom_second) == 0) time_unit = ERL_NIF_SEC; else if (enif_compare(argv[0], atom_millisecond) == 0) @@ -2284,9 +2281,7 @@ static ERL_NIF_TERM time_offset(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg { ErlNifTimeUnit time_unit; - if (argc != 1) - return atom_false; - + assert(argc == 1); if (enif_compare(argv[0], atom_second) == 0) time_unit = ERL_NIF_SEC; else if (enif_compare(argv[0], atom_millisecond) == 0) @@ -2306,9 +2301,7 @@ static ERL_NIF_TERM convert_time_unit(ErlNifEnv* env, int argc, const ERL_NIF_TE ErlNifTime val; ErlNifTimeUnit from, to; - if (argc != 3) - return atom_false; - + assert(argc == 3); if (!enif_get_int64(env, argv[0], &i64)) return enif_make_badarg(env); @@ -3319,7 +3312,7 @@ static int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, Erl } /* Attempt to write the data */ - n = writev(fd, sysiovec, iovcnt); + n = writev(fd, (struct iovec*)sysiovec, iovcnt); saved_errno = errno; if (enif_ioq_size(q) == 0) { @@ -3393,10 +3386,11 @@ static ERL_NIF_TERM ioq(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) if (enif_is_identical(argv[0], enif_make_atom(env, "example"))) { #ifndef __WIN32__ - int fd[2], res = 0, cnt = 0, queue_cnt; + int fd[2], res = 0, cnt = 0; ERL_NIF_TERM tail; char buff[255]; - pipe(fd); + res = pipe(fd); + assert(res == 0); fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_NONBLOCK); fcntl(fd[1], F_SETFL, fcntl(fd[1], F_GETFL) | O_NONBLOCK); @@ -3639,7 +3633,7 @@ static ErlNifFunc nif_funcs[] = {"get_resource", 2, get_resource}, {"release_resource", 1, release_resource}, {"release_resource_from_thread", 1, release_resource_from_thread}, - {"last_resource_dtor_call", 0, last_resource_dtor_call}, + {"last_resource_dtor_call_nif", 0, last_resource_dtor_call_nif}, {"make_new_resource", 2, make_new_resource}, {"check_is", 11, check_is}, {"check_is_exception", 0, check_is_exception}, @@ -3710,7 +3704,7 @@ static ErlNifFunc nif_funcs[] = {"monitor_frenzy_nif", 4, monitor_frenzy_nif}, {"whereis_send", 3, whereis_send}, {"whereis_term", 2, whereis_term}, - {"whereis_thd_lookup", 2, whereis_thd_lookup}, + {"whereis_thd_lookup", 3, whereis_thd_lookup}, {"whereis_thd_result", 1, whereis_thd_result}, {"ioq_nif", 1, ioq}, {"ioq_nif", 2, ioq}, |