You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

远程gen_server进程启动后立即崩溃问题排查求助

Erlang分布式gen_server进程启动后立即崩溃排查

我有一个基于gen_server行为的主控制器模块controller.erl,需要在4台不同PC上创建4个tower.erl进程并实现后续通信。

tower模块的init/1方法已被调用(能看到对应的打印输出),其中设置的定时器本应触发handle_info/2与控制器通信,但4个tower进程启动后立即崩溃,导致该逻辑从未执行。sys:trace无法工作,且tower的terminate/2函数未被调用,无法捕获崩溃原因,而控制器进程运行正常。

控制器模块(controller.erl)核心代码

start_controller() ->
    gen_server:start({global, ?MODULE}, ?MODULE, [], []).

init(_) ->
    global:register_name(controller,self()),
    % Start additional servers on remote nodes
    Node1 = 'a@10.0.2.15',
    Node2 = 'b@10.0.2.15',
    Node3 = 'c@10.0.2.15',
    Node4 = 'd@10.0.2.15',
    BORDERS_1=[XMIN_1,XMAX_1,YMIN_1,YMAX_1] =[0, 400,0,400],
    BORDERS_2 = [XMIN_2,XMAX_2,YMIN_2,YMAX_2] =[401, 800,0,400],
    BORDERS_3 = [XMIN_3,XMAX_3,YMIN_3,YMAX_3] =[0, 400,401,800],
    BORDERS_4 = [XMIN_4,XMAX_4,YMIN_4,YMAX_4] =[401, 800,401,800],
    ETS_1 = ets:new(ets1,[set,named_table]),
    ETS_2 = ets:new(ets2,[set,named_table]),
    ETS_3 = ets:new(ets3,[set,named_table]),
    ETS_4 = ets:new(ets4,[set,named_table]),
    {ok,PID_1} = rpc:call(Node1, tower, start_tower, [BORDERS_1]),
    {ok,PID_2} = rpc:call(Node2, tower, start_tower, [BORDERS_2]),
    {ok,PID_3} = rpc:call(Node3, tower, start_tower, [BORDERS_3]),
    {ok,PID_4} = rpc:call(Node4, tower, start_tower, [BORDERS_4]),
    REF_1 = erlang:monitor(process,PID_1),
    REF_2 = erlang:monitor(process,PID_2),
    REF_3 = erlang:monitor(process,PID_3),
    REF_4 = erlang:monitor(process,PID_4),
    TimerInterval = 500, % milliseconds
    erlang:send_after(TimerInterval, self(), {send_to_graphics}),
    %{ok,State} where State consists of [PID_i,REF_i,ETS_i,XMIN_i,XMAX_i,YMIN_i,YMAX_i]
    State = [{PID_1,REF_1,ETS_1,XMIN_1,XMAX_1,YMIN_1,YMAX_1},{PID_2,REF_2,ETS_2,XMIN_2,XMAX_2,YMIN_2,YMAX_2},{PID_3,REF_3,ETS_3,XMIN_3,XMAX_3,YMIN_3,YMAX_3},{PID_4,REF_4,ETS_4,XMIN_4,XMAX_4,YMIN_4,YMAX_4}],
    {ok, State}.

Tower模块(tower.erl)核心代码

init(Borders) ->
    io:format("The borders for PID ~p are ~p ~n",[self(),Borders]),
    % {ok,FD} = file:open("tower_init.txt",[write]),
    % file:write(FD,"initiated a tower with an rpc call"),
    % file:close(FD),
    [Xmin, Xmax, Ymin, Ymax] = Borders,
    Table = ets:new(planes, [set,public, named_table]),
    StripBusy = 0,
    XStart = 100,
    XEnd = 300,
    YStart = 100,
    YEnd = 300,
    Strip = {XStart,XEnd,YStart,YEnd},
    State = {Table,Strip,{Xmin,Xmax,Ymin,Ymax},StripBusy},
    timer:send_interval(1000, {self(), send_to_controller}), %% Start the timer for plane creation
    {ok,State}.
    
start_tower([Xmin, Xmax, Ymin, Ymax]) ->
    gen_server:start_link({global, ?MODULE}, ?MODULE, [Xmin, Xmax, Ymin, Ymax], []).

handle_info({_PID, send_to_controller},State) ->
    io:format("Sending to main controller ~p ~n",[self()]),
    Controller_PID = global:whereis_name(controller),
    ETS_as_list = tab2list(planes),
    gen_server:cast(Controller_PID,{self(),ETS_as_list}),
    timer:send_interval(1000, {self(), send_to_controller}),
    {noreply,State};

可能的崩溃原因

1. 全局注册名冲突

tower模块的start_tower/1使用gen_server:start_link({global, ?MODULE}, ...)启动进程,这意味着每个tower进程都会尝试向分布式集群的全局注册中心注册名为tower的进程。而全局注册名在整个集群中唯一,只有第一个启动的tower进程能注册成功,后续节点上的tower进程会因为注册失败直接崩溃。

由于gen_server:start_link是关联式启动,注册失败会直接触发进程退出,且此时进程还未完全初始化完成,terminate/2函数不会被调用。

2. ETS命名表冲突

tower的init/1中创建了名为planes的ETS命名表(ets:new(planes, [set,public, named_table])),而每个Erlang节点上的命名表名称也是唯一的:

  • 如果目标节点之前启动过tower进程且未清理planes表,新进程创建同名表时会报错;
  • 即使是首次启动,若存在并发创建的情况(虽然这里是串行rpc调用,但不排除节点间时序问题),也可能导致创建失败。

ETS表创建失败会使init/1抛出异常,直接导致进程崩溃,同样不会触发terminate/2。

3. 分布式全局名称服务同步问题

虽然rpc:call返回了{ok,PID},但分布式集群的global模块可能未完成名称同步,tower进程启动后若在初始化阶段隐含依赖controller的全局名称(虽然当前代码中init/1未直接调用,但不排除其他隐藏逻辑),可能因无法找到控制器进程而崩溃。不过从现有代码看,该可能性低于前两者。

4. Timer调用的冗余问题

tower的handle_info/2中再次调用timer:send_interval/2,会导致不断创建新的定时器,最终可能引发资源耗尽,但这是进程运行后的问题,不会导致启动后立即崩溃,可排除。

内容的提问来源于stack exchange,提问作者user15846642

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:17:05