diff options
author | Paul Joseph Davis <davisp@apache.org> | 2010-03-19 15:20:12 +0000 |
---|---|---|
committer | Paul Joseph Davis <davisp@apache.org> | 2010-03-19 15:20:12 +0000 |
commit | fbcc835d06dc017aebaf0b837bf56ca524f3c9c5 (patch) | |
tree | f14fadf4c356ef3992681cc2b2ebdd948e5ab55b | |
parent | c4cd72b2dfa34e9d20e47ffabf173023bd3ecefb (diff) |
Avoid a possible race condition.
The old code was relying on a DOWN message being sent before a call
to get the current ref counter. Its possible that the request was
sent before that happened causing an error.
The new code doesn't use messages from the child process and instead
uses a monitor to know when the process went down. Then it sends
up to 10,000 requests for the current count. Theoretically the only
way this will fail is if the DOWN message to the ref_counter is
delayed for an extremely long time or dropped entirely.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@925264 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-x | test/etap/100-ref-counter.t | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/test/etap/100-ref-counter.t b/test/etap/100-ref-counter.t index 6f18d828..8f996d04 100755 --- a/test/etap/100-ref-counter.t +++ b/test/etap/100-ref-counter.t @@ -27,17 +27,14 @@ main(_) -> loop() -> receive - {ping, From} -> - From ! pong + close -> ok end. wait() -> receive - _ -> - ok - after - 1000 -> - throw(timeout_error) + {'DOWN', _, _, _, _} -> ok + after 1000 -> + throw(timeout_error) end. test() -> @@ -94,11 +91,23 @@ test() -> "Sanity checking that the Pid was re-added." ), - ChildPid1 ! {ping, self()}, + erlang:monitor(process, ChildPid1), + ChildPid1 ! close, wait(), - etap:is( - couch_ref_counter:count(RefCtr), - 1, + + CheckFun = fun + (Iter, nil) -> + case couch_ref_counter:count(RefCtr) of + 1 -> Iter; + _ -> nil + end; + (_, Acc) -> + Acc + end, + Result = lists:foldl(CheckFun, nil, lists:seq(1, 10000)), + etap:isnt( + Result, + nil, "The referer count was decremented automatically on process exit." ), |