Skip to content

Instantly share code, notes, and snippets.

@etrepum
Created May 10, 2012 20:36
Show Gist options
  • Save etrepum/2655724 to your computer and use it in GitHub Desktop.
Save etrepum/2655724 to your computer and use it in GitHub Desktop.
Cowboy graceful acceptor shutdown
-export([graceful_stop/1, graceful_stop_proc/1]).
graceful_stop(Timeout) ->
lists:foreach(fun stop_listener/1, supervisor:which_children(cowboy_sup)),
proc_lib:spawn(?MODULE, graceful_stop_proc, [Timeout]).
graceful_stop_proc(Timeout) ->
true = register(graceful_stop, self()),
lager:critical("SHUTDOWN with timeout of ~p msec", [Timeout]),
TRef = erlang:start_timer(Timeout, self(), not_so_graceful),
Monitors = sets:from_list(
[erlang:monitor(process, Pid)
|| Pid <- gproc:lookup_pids({p, l, graceful_shutdown})]),
graceful_stop(TRef, Monitors).
graceful_stop(TRef, Monitors) ->
case sets:size(Monitors) of
0 ->
lager:critical("SHUTDOWN gracefully, no more connections"),
erlang:cancel_timer(TRef),
graceful_stop_done();
N ->
lager:critical(
"SHUTDOWN waiting up to ~p msec for ~p connections to shutdown",
[erlang:read_timer(TRef), N]),
receive
{'DOWN', MRef, _Type, _Object, _Info} ->
graceful_stop(TRef, sets:del_element(MRef, Monitors));
{timeout, TRef, not_so_graceful} ->
lager:critical("SHUTDOWN timeout"),
graceful_stop_done();
Msg ->
lager:critical("SHUTDOWN unexpected msg ~p", [Msg]),
graceful_stop(TRef, Monitors)
end
end.
graceful_stop_done() ->
init:stop().
stop_listener({{cowboy_listener_sup, Name}, Pid, _Type, _Mods}) ->
lager:critical("SHUTDOWN stop listening for ~s", [Name]),
[supervisor:terminate_child(Pid, Ref) || Ref <- [cowboy_acceptors_sup,
cowboy_listener]];
stop_listener(_Other) ->
ok.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment