From 68ad03bc3661f4bf82afbbde65a8d04861a6f799 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 13 Feb 2017 18:40:32 +0100 Subject: Expand nif_SUITE:monitor_frenzy with binary_to_term to provoke resource revival race. --- erts/emulator/test/nif_SUITE.erl | 32 +++++++++++++++++++-------- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 29 ++++++++++++++---------- 2 files changed, 40 insertions(+), 21 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 5857ed51e4..d29537e3ef 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -720,6 +720,8 @@ monitored_by(Pid) -> -define(FRENZY_RAND_BITS, 25). +%% Exercise monitoring from NIF resources by randomly +%% create/destruct processes, resources and monitors. monitor_frenzy(Config) -> ensure_lib_loaded(Config), @@ -731,7 +733,7 @@ monitor_frenzy(Config) -> spawn_link(fun() -> SelfPix = monitor_frenzy_nif(init, ?FRENZY_RAND_BITS, 0, 0), unlink(Master), - frenzy(SelfPix, undefined) + frenzy(SelfPix, {undefined, []}) end), receive after 5*1000 -> ok end, @@ -757,7 +759,7 @@ frenzy(SelfPix, State0) -> State1 = frenzy_do_op(SelfPix, Op, (Rnd bsr 2), State0), frenzy(SelfPix, State1). -frenzy_do_op(SelfPix, Op, Rnd, Pid0) -> +frenzy_do_op(SelfPix, Op, Rnd, {Pid0,RBins}=State0) -> case Op of 0 -> % add/remove process Papa = self(), @@ -778,24 +780,36 @@ frenzy_do_op(SelfPix, Op, Rnd, Pid0) -> end, case monitor_frenzy_nif(Op, Rnd, SelfPix, NewPid) of NewPix when is_integer(NewPix) -> - NewPid ! {go, NewPix, undefined}, - undefined; + NewPid ! {go, NewPix, {undefined, []}}, + {undefined, RBins}; ExitPid when is_pid(ExitPid) -> false = (ExitPid =:= self()), exit(ExitPid,die), - NewPid; + {NewPid, RBins}; done -> done end; + + 3 -> + %% Try provoke revival-race of resource from magic ref external format + _ = [binary_to_term(B) || B <- RBins], + {Pid0, []}; _ -> case monitor_frenzy_nif(Op, Rnd, SelfPix, undefined) of - ok -> Pid0; - 0 -> Pid0; - 1 -> Pid0; + Rsrc when ?is_resource(Rsrc) -> + %% Store resource in ext format only, for later revival + State1 = {Pid0, [term_to_binary(Rsrc) | RBins]}, + gc_and_return(State1); + ok -> State0; + 0 -> State0; + 1 -> State0; done -> done end end. +gc_and_return(RetVal) -> + erlang:garbage_collect(), + RetVal. hipe(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), @@ -1171,7 +1185,7 @@ resource_new_do2(Type) -> ResB = make_new_resource(Type, BinB), true = is_reference(ResA), true = is_reference(ResB), - ResA /= ResB, + true = (ResA /= ResB), {PtrA,BinA} = get_resource(Type, ResA), {PtrB,BinB} = get_resource(Type, ResB), true = (PtrA =/= PtrB), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index d5dd379d76..97cb7e55d6 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2669,19 +2669,24 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T } DBG_TRACE2("New resource at r=%p rix=%u\n", r, rix); } - else if (rand_bits(&rnd, 3) == 0) { + else { + unsigned int resource_op = rand_bits(&rnd, 3); r = resv[rix].obj; - resv[rix].obj = NULL; - resv[rix].release_cnt++; - enif_mutex_unlock(resv[rix].lock); - DBG_TRACE2("Delete resource at r=%p rix=%u\n", r, rix); - enif_release_resource(r); - retval = atom_ok; - break; - } - else { - r = resv[rix].obj; - } + if (resource_op == 0) { + resv[rix].obj = NULL; + resv[rix].release_cnt++; + enif_mutex_unlock(resv[rix].lock); + DBG_TRACE2("Delete resource at r=%p rix=%u\n", r, rix); + enif_release_resource(r); + retval = atom_ok; + break; + } + else if (resource_op == 1) { + retval = enif_make_resource(env, r); + enif_mutex_unlock(resv[rix].lock); + break; + } + } enif_keep_resource(r); enif_mutex_unlock(resv[rix].lock); -- cgit v1.2.3