Skip to content

Commit

Permalink
Properly Release locks when owning process exits
Browse files Browse the repository at this point in the history
  • Loading branch information
whitfin committed May 27, 2024
1 parent 85708d7 commit 4adfee7
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/sleeplocks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ handle_call(release, {From, _Ref}, #lock{current = Current} = Lock) ->
NewLock = case maps:is_key(From, Current) of
false -> Lock;
true ->
{MonitorRef, NewCurrent} = maps:take(From, Current),
erlang:demonitor(MonitorRef),
NewCurrent = maps:remove(From, Current),
next_caller(Lock#lock{current = NewCurrent})
end,
Expand All @@ -153,6 +155,11 @@ handle_call(release, {From, _Ref}, #lock{current = Current} = Lock) ->
handle_cast(_Msg, Lock) ->
{noreply, Lock}.

%% @hidden
%% Handles releasing locks if owners crash.
handle_info({'DOWN', _Ref, process, Pid, _Reason}, #lock{current = Current} = Lock) ->
{noreply, Lock#lock{current = maps:remove(Pid, Current)}};

%% @hidden
%% Empty shim to implement behaviour.
handle_info(_Msg, Lock) ->
Expand All @@ -174,7 +181,8 @@ code_change(_Vsn, Lock, _Extra) ->

%% Locks a caller in the internal locks map.
lock_caller({From, _Ref}, #lock{current = Current} = Lock) ->
Lock#lock{current = maps:put(From, ok, Current)}.
Monitor = erlang:monitor(process, From),
Lock#lock{current = maps:put(From, Monitor, Current)}.

%% Attempts to pass a lock to a waiting caller.
next_caller(#lock{waiting = Waiting} = Lock) ->
Expand Down

0 comments on commit 4adfee7

Please sign in to comment.