Erlang:如何在控制Erlang进程崩溃时使连接的外部操作系统进程自动终止?

2024-03-06

我正在使用 Erlang 端口读取 Linux 进程的输出。我希望每当我连接的 Erlang 进程终止时,Linux 进程就会自动终止。从文档来看,在我看来这应该自动发生,但事实并非如此。

最小的例子。将其放入文件 test.erl 中:

-module(test).
-export([start/0, spawn/0]).

start() ->
    Pid = spawn_link(?MODULE, spawn, []),
    register(test, Pid).

spawn() ->
    Port = open_port({spawn, "watch date"},[stream, exit_status]),
    loop([{port, Port}]).

loop(State) ->
    receive
        die ->
            error("died");
        Any ->
            io:fwrite("Received: ~p~n", [Any]),
            loop(State)
    end.

然后,在 erl shell 中:

1> c(test).
{ok,test}
2> test:start().
true

该进程启动并每 2 秒打印一些从 Linux“watch”命令接收到的数据。

然后,我让 Erlang 进程崩溃:

3> test ! die.
=ERROR REPORT==== 26-May-2021::13:24:01.057065 ===
Error in process <0.95.0> with exit value:
{"died",[{test,loop,1,[{file,"test.erl"},{line,15}]}]}

** exception exit: "died"
     in function  test:loop/1 (test.erl, line 15)

Erlang 进程按预期终止,来自“watch”的数据停止出现,但 watch 进程仍然在后台运行,如 Linux(不是 erl)终端中所示:

fuxoft@frantisek:~$ pidof watch
1880127

在我的现实场景中,我没有使用“watch”命令,而是使用其他输出数据且不接受输入的进程。当我连接的 Erlang 进程崩溃时,如何让它自动死亡?我可以使用 Erlang 管理程序来完成此操作,并在 Erlang 进程崩溃时手动发出“kill”命令,但我认为这可以更简单、更干净地完成。


The open_port函数创建一个port()并将其链接到调用过程。如果拥有进程终止,port() closes.

为了与外部生成的命令进行通信,Erlang 创建了多个管道,默认情况下将它们绑定到stdin and stdout外部进程的(文件描述符)。外部进程通过标准输出写入的任何内容都将作为消息到达所属进程。

当。。。的时候Port关闭时,将其连接到外部进程的管道已损坏,因此尝试读取或写入它们将给您一个 SIGPIPE/EPIPE。

当从 FD 写入或读取并退出该进程时,您可以从外部进程中检测到这一点。

例如:使用当前代码,您可以使用以下命令检索外部进程操作系统 pidproplists:get_value(os_pid, erlang:port_info(Port))。如果你strace它,你会看到:

write(1, ..., 38) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=31297, si_uid=1001} ---

端口和 Erlang 中的 SIGPIPE

看起来虽然 SIGPIPE 的默认操作是终止进程,但 Erlang 将其设置为忽略该信号(因此子进程继承了此配置)。

如果您无法修改外部进程代码来检测 EPIPE,您可以使用此 c 包装器来重置操作:

#include <unistd.h>
#include <signal.h>

int main(int argc, char* argv[]) {
    if (signal(SIGPIPE, SIG_DFL) == SIG_ERR)
        return 1;
    if (argc < 2)
        return 2;
    execv(argv[1], &(argv[1]));
}

只需编译它并运行它wrapper path-to-executable [arg1 [arg2 [...]]] with open_port

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Erlang:如何在控制Erlang进程崩溃时使连接的外部操作系统进程自动终止? 的相关文章

  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我
  • 如何使用 GOPATH 的 Samba 服务器位置?

    我正在尝试将 GOPATH 设置为共享网络文件夹 当我进入 export GOPATH smb path to shared folder I get go GOPATH entry is relative must be absolute
  • 如何更改 Apache 服务器的根目录? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何更改 Apache 服务器的文档根目录 我基本上想要localhost从 来 users spencer projects目录而不是
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • MySQL 中的创建/写入权限

    我的设备遇到一些权限问题SELECT INTO OUTFILE陈述 当我登录数据库并执行简单的导出命令时 例如 mysql gt select from XYZ into outfile home mropa Photos Desktop
  • php exec 返回的结果比直接进入命令行要少

    我有一个 exec 命令 它的行为与通过 Penguinet 给 linux 的相同命令不同 res exec cd mnt mydirectory zcat log file gz echo res 当将命令直接放入命令行时 我在日志文件
  • 如何减去两个 gettimeofday 实例?

    我想减去两个 gettimeofday 实例 并以毫秒为单位给出答案 这个想法是 static struct timeval tv gettimeofday tv NULL static struct timeval tv2 gettime
  • 使用 Grep 查找两个短语之间的文本块(包括短语)

    是否可以使用 grep 来高亮所有以以下内容开头的文本 mutablePath CGPathCreateMutable 并以以下内容结尾 CGPathAddPath skinMutablePath NULL mutablePath 这两个短
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • 如何构建任务“gems:install”

    我正在将 Rails 应用程序部署到 Linux 服务器 并且缺少一些 rake 任务 包括 rake gems install 和 rake db 我正在运行来自 GEM 的 Rails 2 3 4 为什么是这样 我该如何解决 我可以以某
  • NUMA 在虚拟内存中是如何表示的?

    有许多资源 https en wikipedia org wiki Non uniform memory access从硬件角度描述NUMA的架构性能影响 http practical tech com infrastructure num
  • Windows CE 与嵌入式 Linux [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 现在我确信我们都清楚 Linux 与 Windows 桌面的相对优点 然而 我对嵌入式开发世界的了解却少得多 我主要对行业解决方案感兴
  • 在 Mac OSX 上交叉编译 x86_64-unknown-linux-gnu 失败

    我尝试将我的 Rust 项目之一编译到 x86 64 unknown linux gnu 目标 cargo build target x86 64 unknown linux gnu Compiling deployer v0 1 0 fi
  • 在 C++ linux 中将 STRINGS 写入串口

    我知道这个问题遍布互联网 但仍然没有任何东西能让我完全解决这个问题 我想用 C linux 将数据写入 Propeller 板的串行端口 从控制台获取输入时程序运行良好 但是当我向它写入字符串时总是返回 ERROR Invalid comm
  • 如何允许应用程序声明“https”方案 URI? (即如何从 https URL 打开桌面应用程序?)

    目前我正在尝试为 OAuth 2 0 授权流程创建一个客户端 实际上是一个本机应用程序 并且在规范中就在这儿 https www rfc editor org rfc rfc8252 section 7 2据说有 3 种方法来处理重定向 U
  • Linux 上的基准测试程序

    对于一项任务 我们需要使用不同的优化和参数来对我们的实现进行基准测试 有没有一种可行的方法可以在Linux命令行 我知道时间 上使用不同的参数对小程序进行基准测试 从而为我提供CSV或类似内容的时间数据 输出可能类似于 Implementa
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有
  • linux命令中括号的用途是什么[重复]

    这个问题在这里已经有答案了 我在 Linux 终端中运行以下命令 谁能告诉我 Linux 终端中括号和以下命令的用途是什么 echo GET HTTP 1 0 echo 主机 www google com echo 数控 www googl
  • Raspberry 交叉编译 - 执行程序以“分段错误”结束

    我有一个自己编写的程序 我想从我的 x86 机器上为 Raspberry Pi 构建它 我正在使用 eclipse 生成的 makefile 并且无法更改此内容 我已经阅读了 CC for raspi 的教程 Hackaday 链接 htt
  • 使用 inotify 的正确方法是什么?

    我想使用inotifyLinux 上的机制 我希望我的应用程序知道文件何时aaa被改变了 您能给我提供一个如何做到这一点的示例吗 文档 来自监视文件系统活动 inotify https developer ibm com tutorials

随机推荐