erlang 保持进程活动只是为了链接其他进程

brtdzjyr  于 2022-12-16  发布在  Erlang
关注(0)|答案(1)|浏览(197)

在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

如果一个工作进程崩溃,则父进程崩溃,然后其余的工作进程也崩溃。但是,如果所有工作进程正常退出,则父进程将永远存在,尽管处于挂起状态。
虽然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.
txu3uszq

txu3uszq1#

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

相关问题