Author: davisp
Date: Fri Mar 19 15:20:12 2010
New Revision: 925264
URL: http://svn.apache.org/viewvc?rev=925264&view=rev
Log:
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.
Modified:
couchdb/trunk/test/etap/100-ref-counter.t
Modified: couchdb/trunk/test/etap/100-ref-counter.t
URL:
http://svn.apache.org/viewvc/couchdb/trunk/test/etap/100-ref-counter.t?rev=925264&r1=925263&r2=925264&view=diff
==============================================================================
--- couchdb/trunk/test/etap/100-ref-counter.t (original)
+++ couchdb/trunk/test/etap/100-ref-counter.t Fri Mar 19 15:20:12 2010
@@ -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."
),