Skip to content
This repository has been archived by the owner on Oct 22, 2021. It is now read-only.

Commit

Permalink
Fix badarg error in couch_server:try_close_lru/1
Browse files Browse the repository at this point in the history
The race condition in couch_server's ets table usage rears its ugly head
by leaving an entry in couch_lru. This patch just addresses the issue by
allowing the client pid to use the db and ignores the fact that for the
duration its over the max_dbs_open setting.
  • Loading branch information
davisp committed Oct 13, 2011
1 parent 6947cab commit 7c04f93
Showing 1 changed file with 21 additions and 9 deletions.
30 changes: 21 additions & 9 deletions apps/couch/src/couch_server.erl
Expand Up @@ -199,16 +199,28 @@ try_close_lru(StartTime) ->
% There may exist an extremely small possibility of a race % There may exist an extremely small possibility of a race
% condition here, if a process could lookup the DB before the lock, % condition here, if a process could lookup the DB before the lock,
% but fail to monitor the fd before the is_idle check. % but fail to monitor the fd before the is_idle check.
true = ets:update_element(couch_dbs, DbName, {#db.fd_monitor, locked}), %
[#db{main_pid = Pid} = Db] = ets:lookup(couch_dbs, DbName), % If we do hit this race condition the behavior is that the process
case couch_db:is_idle(Db) of true -> % grabbing the database will end up inserting a value into the
true = ets:delete(couch_dbs, DbName), % couch_lru table. Its possible that we end up picking that up
true = ets:delete(couch_lru, DbName), % as the DbName above to close. So we here we'll just remove the
exit(Pid, kill), % couch_lru entry and ignore it.
ok; case ets:update_element(couch_dbs, DbName, {#db.fd_monitor, locked}) of
true ->
[#db{main_pid = Pid} = Db] = ets:lookup(couch_dbs, DbName),
case couch_db:is_idle(Db) of true ->
true = ets:delete(couch_dbs, DbName),
true = ets:delete(couch_lru, DbName),
exit(Pid, kill),
ok;
false ->
Update = {#db.fd_monitor, nil},
true = ets:update_element(couch_dbs, DbName, Update),
true = ets:insert(couch_lru, {DbName, now()}),
try_close_lru(StartTime)
end;
false -> false ->
true = ets:update_element(couch_dbs, DbName, {#db.fd_monitor, nil}), true = ets:delete(couch_lru, DbName),
true = ets:insert(couch_lru, {DbName, now()}),
try_close_lru(StartTime) try_close_lru(StartTime)
end end
end. end.
Expand Down

0 comments on commit 7c04f93

Please sign in to comment.