Elixir - 受监督的进程似乎会阻止程序执行

Posted

技术标签:

【中文标题】Elixir - 受监督的进程似乎会阻止程序执行【英文标题】:Elixir - Supervised processes appear to block program execution 【发布时间】:2015-06-12 14:03:14 【问题描述】:

写了一些小实验来熟悉这门语言,但遇到了一个我猜是初级的问题。

我有一个简单的主管,有 3 个简单的工人:

def init do 
    Supervisor.start_link(
       [
          worker(__MODULE__, [:"process-1"], [function: :test, id: :"p-1"]),
          worker(__MODULE__, [:"process-2"], [function: :test, id: :"p-2"]),
          worker(__MODULE__, [:"process-3"], [function: :test, id: :"p-3"])
       ],
       strategy: :one_for_one   
    )
end

":test" 看起来像这样:

def test(name) do
    flag(:trap_exit, true)

    IO.puts "Testing: #name == #inspect self"

    register(self, name)

    receive do
         :death  -> 
            IO.puts("I WOZ MURDERED!")
            exit(self, "Ex process...")
         :life  -> 
            IO.puts("#inspect self is listening...") 
            __MODULE__.test(name)
         :EXIT, pid, reason  ->
            IO.puts "REASON: #inspect reason - PROCESS: #inspect pid"
    end
end

这会编译,但它只会产生一个进程,并挂起/阻塞 iex。

相比之下,当我使用简单的“spawn_link”进程链时,所有三个(或多个)进程同时启动并将控制权返回给 iex shell,以便我可以从命令行发送注册进程消息。

目前,我的意图是创建一个 OTP 主管,运行并注册三个(或多个)工作进程并将它们附加到主管,发送一个简单的消息来杀死给定的工作,然后让主管重新启动它。

我做错了什么?

【问题讨论】:

【参考方案1】:

问题是您作为工作人员规范的一部分提供的 function: 没有达到 OTP 的预期。

来自http://www.erlang.org/doc/man/supervisor.html

启动函数必须创建并链接到子进程,并且 应该返回 ok,Child 或 ok,Child,Info 其中 Child 是 pid 子进程和 Info 一个被忽略的任意术语 主管。

您的代码不会产生子代,而是进入接收循环。你或许可以使用 Elixir 的 Task 模块来做一些类似于你想要的事情:

worker(Task, [__MODULE__, :test, [:"process-1"]], id: :"p-1"),
worker(Task, [__MODULE__, :test, [:"process-2"]], id: :"p-2"),
worker(Task, [__MODULE__, :test, [:"process-3"]], id: :"p-3")

但是,如果您想了解有关 OTP 功能的更多信息,那么尝试实施自己的 GenServer 可能是更好的选择。

【讨论】:

以上是关于Elixir - 受监督的进程似乎会阻止程序执行的主要内容,如果未能解决你的问题,请参考以下文章

Elixir - 在监督下启动 Java JInterface OTP 节点

Erlang - Elixir:啥是监督树?

阻塞和非阻塞子进程调用

为啥有一个监督树而不是一个集中的监督者?

同步异步阻塞非阻塞

在运行不受信任的用户代码时阻止 Node.js 中的系统调用