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

Erlang带监控进程创建:my_spawn函数实现与竞态条件问询

Race-Free Implementation of my_spawn in Erlang

Great question! The core issue with the naive approach (spawning then monitoring) is that those two steps aren't atomic—there's a small but critical window where the spawned process could crash before the monitor is set up, leaving you with no way to track its termination.

Erlang gives us a built-in solution for exactly this scenario: spawn_monitor/3, which performs the spawn and monitor operations as a single atomic action. This eliminates the race condition entirely.

Here's the Implementation

my_spawn(Mod, Func, Args) ->
    % Atomically spawn the process and set up monitoring
    {Pid, MonitorRef} = spawn_monitor(Mod, Func, Args),
    % Record the start time (using milliseconds for readability)
    StartTime = erlang:system_time(millisecond),
    % Spawn a dedicated listener process to handle the 'DOWN' message
    spawn(fun() ->
        receive
            {'DOWN', MonitorRef, process, Pid, TerminationReason} ->
                EndTime = erlang:system_time(millisecond),
                io:format("Process ~p terminated with reason: ~p. It lived for ~p ms.~n",
                          [Pid, TerminationReason, EndTime - StartTime])
        end
    end),
    % Return the PID just like the standard spawn/3 does
    Pid.

How This Fixes the Race Condition

  • spawn_monitor/3 is guaranteed by the Erlang VM to either:
    1. Successfully create the process and attach the monitor, or
    2. Fail entirely (if spawning isn't possible).
      There's no in-between state where the process exists but isn't monitored.
  • The dedicated listener process waits exclusively for the {'DOWN'} message tied to our monitor reference, so it won't interfere with other monitoring operations in your system.

Testing It Out

Let's make a quick test module to verify it works for both crashes and normal exits:

-module(test_my_spawn).
-export([test_crash/0, test_normal_exit/0]).

test_crash() ->
    my_spawn(test_my_spawn, crash, []).

crash() ->
    % Force an error to test abnormal termination
    erlang:error(oops).

test_normal_exit() ->
    my_spawn(test_my_spawn, normal_exit, []).

normal_exit() ->
    % Exit normally after doing nothing
    ok.

If you run test_my_spawn:test_crash(). in the Erlang shell, you'll see output like:

Process <0.145.0> terminated with reason: oops. It lived for 2 ms.

And test_my_spawn:test_normal_exit(). will print:

Process <0.147.0> terminated with reason: normal. It lived for 1 ms.

This implementation matches the behavior of spawn/3 exactly, while reliably tracking termination details without any race conditions.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:31:03