summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_rep_changes_feed.erl
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@apache.org>2010-09-16 00:08:32 +0000
committerFilipe David Borba Manana <fdmanana@apache.org>2010-09-16 00:08:32 +0000
commit1679a7829e61cf3e06096e17439a7eadedd7ac03 (patch)
tree10f8228e92466b541c99acc1be31193ec2385daa /src/couchdb/couch_rep_changes_feed.erl
parent4d0abd7052f4aa951e49a3dbcae52e24141b0b4c (diff)
Replicator bug fix: properly stop link worker processes to avoid noproc exceptions crashing the replicator's changes feed reader process.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@997547 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_rep_changes_feed.erl')
-rw-r--r--src/couchdb/couch_rep_changes_feed.erl24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/couchdb/couch_rep_changes_feed.erl b/src/couchdb/couch_rep_changes_feed.erl
index a8c77b18..3f6079e7 100644
--- a/src/couchdb/couch_rep_changes_feed.erl
+++ b/src/couchdb/couch_rep_changes_feed.erl
@@ -43,7 +43,8 @@ next(Server) ->
gen_server:call(Server, next_changes, infinity).
stop(Server) ->
- gen_server:call(Server, stop).
+ catch gen_server:call(Server, stop),
+ ok.
init([Parent, #http_db{}=Source, Since, PostProps]) ->
process_flag(trap_exit, true),
@@ -95,7 +96,7 @@ init([Parent, #http_db{}=Source, Since, PostProps]) ->
ibrowse:stream_next(ReqId),
{ok, #state{conn=Pid, last_seq=Since, reqid=ReqId, init_args=Args}};
{ibrowse_async_headers, ReqId, Code, Hdrs} when Code=="301"; Code=="302" ->
- catch ibrowse:stop_worker_process(Pid),
+ stop_link_worker(Pid),
Url2 = couch_rep_httpc:redirect_url(Hdrs, Req#http_db.url),
Req2 = couch_rep_httpc:redirected_request(Req, Url2),
Pid2 = couch_rep_httpc:spawn_link_worker_process(Req2),
@@ -108,7 +109,7 @@ init([Parent, #http_db{}=Source, Since, PostProps]) ->
{stop, changes_timeout}
end;
{ibrowse_async_headers, ReqId, "404", _} ->
- catch ibrowse:stop_worker_process(Pid),
+ stop_link_worker(Pid),
?LOG_INFO("source doesn't have _changes, trying _all_docs_by_seq", []),
Self = self(),
BySeqPid = spawn_link(fun() -> by_seq_loop(Self, Source, Since) end),
@@ -207,8 +208,9 @@ handle_info({'EXIT', From, Reason}, #state{changes_loop=From} = State) ->
?LOG_ERROR("changes_loop died with reason ~p", [Reason]),
{stop, changes_loop_died, State};
-handle_info({'EXIT', _From, normal}, State) ->
- {noreply, State};
+handle_info({'EXIT', From, Reason}, State) ->
+ ?LOG_ERROR("changes loop, process ~p died with reason ~p", [From, Reason]),
+ {stop, {From, Reason}, State};
handle_info(Msg, #state{init_args = InitArgs} = State) ->
case Msg of
@@ -227,8 +229,7 @@ terminate(_Reason, State) ->
conn = Conn
} = State,
if is_pid(ChangesPid) -> exit(ChangesPid, stop); true -> ok end,
- if is_pid(Conn) -> catch ibrowse:stop_worker_process(Conn); true -> ok end,
- ok.
+ stop_link_worker(Conn).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -271,7 +272,7 @@ handle_headers(200, _, State) ->
{noreply, State};
handle_headers(Code, Hdrs, #state{init_args = InitArgs} = State)
when Code =:= 301 ; Code =:= 302 ->
- catch ibrowse:stop_worker_process(State#state.conn),
+ stop_link_worker(State#state.conn),
[Parent, #http_db{url = Url1} = Source, Since, PostProps] = InitArgs,
Url = couch_rep_httpc:redirect_url(Hdrs, Url1),
Source2 = couch_rep_httpc:redirected_request(Source, Url),
@@ -389,3 +390,10 @@ maybe_stream_next(#state{complete=false, count=N} = S) when N < ?BUFFER_SIZE ->
ibrowse:stream_next(S#state.reqid);
maybe_stream_next(_) ->
timer:cancel(get(timeout)).
+
+stop_link_worker(Conn) when is_pid(Conn) ->
+ unlink(Conn),
+ receive {'EXIT', Conn, _} -> ok after 0 -> ok end,
+ catch ibrowse:stop_worker_process(Conn);
+stop_link_worker(_) ->
+ ok.