emqx / esockd

Erlang general non-blocking TCP/SSL socket server
https://www.emqx.com
Apache License 2.0
211 stars 84 forks source link

fix: stop process when receive udp_error/udp_closed #187

Closed zhongwencool closed 7 months ago

zhongwencool commented 7 months ago

we may receive udp_error or udp_closed: https://github.com/erlang/otp/blob/e6d340156dc4c483293466b2c7a883c08173751e/lib/kernel/test/gen_udp_SUITE.erl#L644-L652

https://github.com/erlang/otp/blob/master/erts/emulator/drivers/common/inet_drv.c#L4141-L4150

Test cert file is expired at 2024 Jan 13, so we update to 2034

openssl x509 -noout -text -in ca.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            6c:95:41:10:01:26:ab:db:88:8e:ed:1a:42:21:10:60:82:a3:65:c8
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = CN, ST = emqx, O = esockd, CN = CA
        Validity
            Not Before: Dec 14 19:37:43 2023 GMT
            Not After : Jan 13 19:37:43 2024 GMT
        Subject: C = CN, ST = emqx, O = esockd, CN = CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
zmstone commented 7 months ago

please describe what happens after the error. is it restarted by the supervisor? is it going to cause error escalation to the supervisor ?

zhongwencool commented 7 months ago

please describe what happens after the error. is it restarted by the supervisor? is it going to cause error escalation to the supervisor ?

I use a gen_server to monitor this udp pid. when this udp process exit, the monitor will exit too, then the whole supervisor will be restarted.

init([Size, Port]) ->
    SupFlag = #{strategy => rest_for_one, intensity => 300, period => 6},
    PoolSpecs =
        [
            #{
                id => emqx_udp_monitor,
                start => {emqx_udp_monitor, start_link, [Size, Port]},
                restart => permanent,
                shutdown => infinity,
                type => worker
            },
            #{
                id => emqx_dispatcher_sup,
                start => {emqx_dispatcher_sup, start_link, [Size]},
                restart => permanent,
                shutdown => infinity,
                type => supervisor,
                modules => [?MODULE]
            }
        ],
    {ok, {SupFlag, PoolSpecs}}.
-module(emqx_udp_monitor).

-behaviour(gen_server).

-include_lib("emqx/include/logger.hrl").

-export([start_link/2]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link(Size, Port) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [Size, Port], []).

init([Size, Port]) ->
    {ok, Pid} = open_udp(Size, Port),
    _ = process_flag(trap_exit, true),
    erlang:monitor(process, Pid),
    {ok, #{port => Port, udp => Pid}}.

handle_info(Request, State = #{}) ->
    ?SLOG(emergency, #{
        msg => "udp_monitory_receive_unknown_msg_cause_udp_restart",
        request => Request
    }),
    {stop, Request, State}.

terminate(_Reason, _State = #{port := Port}) ->
    _ = close_udp(Port),
    ok.

code_change(_OldVsn, State = #{}, _Extra) ->
    {ok, State}.

open_udp(Size, Port) ->
    Options = [
        %% esockd is not support acceptors option, acceptors is always 1.
        {acceptors, 1},
        {shutdown, brutal_kill},
        {udp_options, [
            {active, true},
            {mode, binary},
            {sndbuf, 81920},
            {recbuf, 81920}
            %{debug, true}
        ]}
    ],
    MFA = {emqx_custom_udp_xxx, start_link, [Size]},
    esockd:open_udp(?MODULE, Port, Options, MFA).

close_udp(Port) ->
    esockd:close({?MODULE, Port}).
zmstone commented 7 months ago

Mem leak! Should change to receive EXIT messages instead To support hot-beam upgrade, the DOWN clause should be kept.

zmstone commented 7 months ago

Mem leak! Should change to receive EXIT messages instead To support hot-beam upgrade, the DOWN clause should be kept.

Never mind, there is already a EXIT handler