让一个进程仅对 link 个其他进程保持活动状态

Keeping a process alive just to link other processes

在 Joe Armstrong 的 Programming Erlang 中,第 12 章,“制作一组一起消亡的进程”,给出了以下代码:

% (Some variables are renamed and comments added for extra clarity)

start(WorkerFuns) ->
    spawn(fun() ->
        % Parent process
        [spawn_link(WorkerFun) || WorkerFun <- WorkerFuns],
        receive
            after infinity -> true
        end
    end).

生成的进程链接如下:

         +- parent -+
        /      |     \
       /       |      \
worker1     worker2 .. workerN

如果一个 worker 崩溃了,那么 parent 崩溃了,然后剩下的 worker 也崩溃了。但是,如果所有worker都正常退出,那么父进程永远存在,尽管处于挂起状态。

虽然 Erlang 进程应该是廉价的,但如果 start/1 在长 运行 服务中被多次调用,一个进程——父进程——似乎每次都被“泄漏”工人正常退出

这在实践中有过问题吗?当所有工作人员正常退出时(见下文),额外的代码是否值得?

start(WorkerFuns) ->
    spawn(fun() ->
        % Parent process
        process_flag(trap_exit, true),
        [spawn_link(WorkerFun) || WorkerFun <- WorkerFuns],
        parent_loop(length(WorkerFuns))
    end).

parent_loop(0) ->
    % All workers exited normally
    true;
parent_loop(RemainingWorkers) ->
    receive
        {'EXIT', _WorkerPid, normal} ->
            parent_loop(RemainingWorkers - 1);
        {'EXIT', _WorkerPid, CrashReason} ->
            exit(CrashReason)
    end.

您的分析是正确的。给出的代码不考虑工人的正常终止,并将留下一个悬空的过程。 space 泄漏将是每次调用约 2 kb,因此在大型系统中,除非您调用 start/1 一千次或更多次,否则您不太可能注意到它,但对于预期 运行 "forever" 你绝对应该添加额外的代码。