Skip to content

Commit

Permalink
Fix halfway-stopping of listeners
Browse files Browse the repository at this point in the history
* if the process calling ranch:stop_listener crashes before finishing,
  the stopping is still exetuted completely
* if a listener is terminated but not deleted, calling ranch:stop_listener
  removes the remnant
  • Loading branch information
juhlig committed Jun 25, 2024
1 parent a8f31f3 commit 7a3aa3b
Showing 1 changed file with 33 additions and 15 deletions.
48 changes: 33 additions & 15 deletions src/ranch.erl
Original file line number Diff line number Diff line change
Expand Up @@ -193,24 +193,42 @@ start_error(_, Error) -> Error.

-spec stop_listener(ref()) -> ok | {error, not_found}.
stop_listener(Ref) ->
Parent = self(),
Tag = make_ref(),
{StopperPid, StopperMon} = spawn_monitor(fun() -> Parent ! {Tag, stop_listener1(Ref)} end),
receive
{Tag, Result} ->
demonitor(StopperMon, [flush]),
Result;
{'DOWN', StopperMon, process, StopperPid, Error} ->
{error, Error}
end.

stop_listener1(Ref) ->
TransportAndOpts = maybe_get_transport_and_opts(Ref),
case supervisor:terminate_child(ranch_sup, {ranch_listener_sup, Ref}) of
ok ->
_ = supervisor:delete_child(ranch_sup, {ranch_listener_sup, Ref}),
ranch_server:cleanup_listener_opts(Ref),
stop_listener2(TransportAndOpts);
{error, _} = Error ->
Error
end.

stop_listener2({Transport, TransOpts}) ->
Transport:cleanup(TransOpts),
ok;
stop_listener2(undefined) ->
ok.

maybe_get_transport_and_opts(Ref) ->
try
[_, Transport0, _, _, _] = ranch_server:get_listener_start_args(Ref),
TransOpts0 = get_transport_options(Ref),
{Transport0, TransOpts0}
of
{Transport, TransOpts} ->
case supervisor:terminate_child(ranch_sup, {ranch_listener_sup, Ref}) of
ok ->
_ = supervisor:delete_child(ranch_sup, {ranch_listener_sup, Ref}),
ranch_server:cleanup_listener_opts(Ref),
Transport:cleanup(TransOpts),
ok;
{error, Reason} ->
{error, Reason}
end
[_, Transport, _, _, _] = ranch_server:get_listener_start_args(Ref),
TransOpts = get_transport_options(Ref),
{Transport, TransOpts}
catch
error:badarg ->
{error, not_found}
undefined
end.

-spec suspend_listener(ref()) -> ok | {error, any()}.
Expand Down

0 comments on commit 7a3aa3b

Please sign in to comment.