diff options
author | Damien F. Katz <damien@apache.org> | 2008-08-24 17:52:56 +0000 |
---|---|---|
committer | Damien F. Katz <damien@apache.org> | 2008-08-24 17:52:56 +0000 |
commit | e9f4150f9d325ebf35c0db37ce2796ec8d240e0d (patch) | |
tree | 66a0e642d7815f042476a6da6e35126641551154 /src/couchdb | |
parent | 50d8dcda77661677c1bd2cf9a557afc6e065441b (diff) |
fix for occasional crash when attempting to open a database on a heavily loaded server
git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@688540 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb')
-rw-r--r-- | src/couchdb/couch_file.erl | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/src/couchdb/couch_file.erl b/src/couchdb/couch_file.erl index 8101fdd2..13ce3aad 100644 --- a/src/couchdb/couch_file.erl +++ b/src/couchdb/couch_file.erl @@ -363,12 +363,16 @@ handle_call({append_bin, Bin}, _From, Fd) -> {ok, Pos} = file:position(Fd, eof), {reply, {file:pwrite(Fd, Pos, Bin2), Pos}, Fd}; handle_call({pread_bin, Pos}, _From, Fd) -> - {ok, <<TermLen:32>>} - = file:pread(Fd, Pos, 4), + {ok, <<TermLen:32>>} = file:pread(Fd, Pos, 4), {ok, Bin} = file:pread(Fd, Pos + 4, TermLen), {reply, {ok, Bin}, Fd}; handle_call({add_ref, Pid},_From, Fd) -> - undefined = put(Pid, erlang:monitor(process, Pid)), + case get(Pid) of + undefined -> + put(Pid, {erlang:monitor(process, Pid), 1}); + {MonRef, RefCnt} -> + put(Pid, {MonRef, RefCnt + 1}) + end, {reply, ok, Fd}; handle_call(num_refs, _From, Fd) -> {monitors, Monitors} = process_info(self(), monitors), @@ -382,9 +386,15 @@ handle_cast({close_maybe, Pid}, Fd) -> catch unlink(Pid), maybe_close_async(Fd); handle_cast({drop_ref, Pid}, Fd) -> - % don't check return of demonitor. The process could haved crashed causing - % the {'DOWN', ...} message to be sent and the process unmonitored. - erlang:demonitor(erase(Pid), [flush]), + case get(Pid) of + {MonRef, 1} -> + erase(Pid), + % don't check return of demonitor. The process could haved crashed causing + % the {'DOWN', ...} message to be sent and the process unmonitored. + erlang:demonitor(MonRef, [flush]); + {MonRef, Num} -> + put(Pid, {MonRef, Num-1}) + end, maybe_close_async(Fd). @@ -392,7 +402,7 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_info({'DOWN', MonitorRef, _Type, Pid, _Info}, Fd) -> - MonitorRef = erase(Pid), + {MonitorRef, _RefCount} = erase(Pid), maybe_close_async(Fd); handle_info(Info, Fd) -> exit({error, {Info, Fd}}). |