summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Joseph Davis <davisp@apache.org>2010-03-19 15:20:12 +0000
committerPaul Joseph Davis <davisp@apache.org>2010-03-19 15:20:12 +0000
commitfbcc835d06dc017aebaf0b837bf56ca524f3c9c5 (patch)
treef14fadf4c356ef3992681cc2b2ebdd948e5ab55b
parentc4cd72b2dfa34e9d20e47ffabf173023bd3ecefb (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-xtest/etap/100-ref-counter.t31
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."
),