关于erlang:erlang-cowboy-在-nginx-499-时的-handler-process-shutdown
简述erlang 的 cowboy 是一个 web server 框架。它在客户端提前断开(nginx http code 499)时,会间接杀掉handler过程。这很容易造成bug。 示例代码参考 https://ninenines.eu/docs/en/...有handler代码如下: -module(hello_handler).-behavior(cowboy_handler).-export([init/2]).init(Req, State) -> erlang:display("before_sleep"), timer:sleep(3000), erlang:display("after_sleep"), Req = cowboy_req:reply( 200, #{<<"content-type">> => <<"text/plain">>}, <<"Hello Erlang!">>, Req ), {ok, Req, State}.在 curl http://localhost:8080时,有输入: ([email protected])1> "before_sleep""after_sleep"如果 curl http://localhost:8080 --max-time 0.001curl: (28) Resolving timed out after 4 milliseconds有输入: ([email protected])1> "before_sleep"这个阐明handler过程的执行被抢行掐断了。如果代码中有对过程内部资源的拜访,比方加锁,显然会造成锁开释问题。 问题起因见 cowboy_http.erl:loop loop(State=#state{parent=Parent, socket=Socket, transport=Transport, opts=Opts, buffer=Buffer, timer=TimerRef, children=Children, in_streamid=InStreamID, last_streamid=LastStreamID}) -> Messages = Transport:messages(), InactivityTimeout = maps:get(inactivity_timeout, Opts, 300000), receive %% Discard data coming in after the last request %% we want to process was received fully. {OK, Socket, _} when OK =:= element(1, Messages), InStreamID > LastStreamID -> loop(State); %% Socket messages. {OK, Socket, Data} when OK =:= element(1, Messages) -> parse(<< Buffer/binary, Data/binary >>, State); {Closed, Socket} when Closed =:= element(2, Messages) -> terminate(State, {socket_error, closed, 'The socket has been closed.'}); {Error, Socket, Reason} when Error =:= element(3, Messages) -> terminate(State, {socket_error, Reason, 'An error has occurred on the socket.'}); {Passive, Socket} when Passive =:= element(4, Messages); %% Hardcoded for compatibility with Ranch 1.x. Passive =:= tcp_passive; Passive =:= ssl_passive -> setopts_active(State), loop(State); %% Timeouts.最终会通过发送exit音讯形式,杀掉children过程。 ...