[英]Await an OTP process to exit
Suppose you have an OTP process whose completion you want to synchronously wait on (where "completion" may be a normal exit or a crash, stop, etc.).假设您有一个 OTP 进程,您希望同步等待其完成(其中“完成”可能是正常退出或崩溃、停止等)。
Suppose further that for business reasons, you can't spawn this process with Task.async/1
or related Task
utilities—it has to be a "normal" process not dependent on Task.await/2
.进一步假设出于业务原因,您不能使用
Task.async/1
或相关的Task
实用程序生成此进程——它必须是一个不依赖于Task.await/2
的“正常”进程。
Is there a better way to do this than simply intermittently polling Process.alive?/1
?有没有比简单地间歇性地轮询
Process.alive?/1
更好的方法Process.alive?/1
? This strikes me as the sort of thing there's probably an established pattern for, but for the life of me I can't find it.这让我印象深刻,因为这种事情可能有一个既定的模式,但对于我的生活,我找不到它。
def await(pid, timeout) when timeout <= 0 do
if Process.alive?(pid) do
Process.exit(pid, :kill) # (or however you want to handle timeouts)
end
end
@await_sleep_ms 500
def await(pid, timeout) do
# Is there a better way to do this?
if Process.alive?(pid) do
:timer.sleep(@await_sleep_ms)
await(pid, subtract_timeout(timeout, @await_sleep_ms))
end
end
The Process.monitor/1
function monitors the given process from the calling process. Process.monitor/1
函数从调用进程监视给定进程。 Combining this with receive
, you can react to your process mailbox.将此与
receive
结合使用,您可以对您的流程邮箱做出反应。
defmodule Await do
def spawn do
Kernel.spawn(fn -> :timer.sleep(2000) end)
end
def await_down(pid) do
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, :process, ^pid, _reason} = message -> {:ok, message}
after
3000 -> {:error, :timeout}
end
end
end
pid = Await.spawn()
# => #PID<0.332.0>
Await.await_down(pid)
# => {:ok, {:DOWN, #Reference<0.4083290149.3661365255.180715>, :process, #PID<0.332.0>, :normal}}
Note the pattern matching inside the receive block, to ensure not only the message is from your process, but that is comes from that specific monitoring.注意接收块内的模式匹配,以确保消息不仅来自您的进程,而且来自特定的监控。
It looks like Process.monitor/1
might be what you're looking for?看起来
Process.monitor/1
可能是你要找的? Example from the docs:文档中的示例:
pid = spawn(fn -> 1 + 2 end)
#=> #PID<0.118.0>
Process.monitor(pid)
#=> #Reference<0.906660723.3006791681.40191>
Process.exit(pid, :kill)
#=> true
receive do
msg -> msg
end
#=> {:DOWN, #Reference<0.906660723.3006791681.40191>, :process, #PID<0.118.0>, :noproc}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.