c - 退出时从子进程传播 WTERMSIG 退出代码

标签 c unix posix

我正在编写一个包装器命令,该命令调用子进程、等待其退出并传播其退出代码。足够简单。

我想将子进程的退出状态传播到我自己进程的退出代码即使子进程通过信号退出。如果 WIFSIGNALED(cmdret) 对于某些包含 waitpid(...) 调用或类似调用结果的 int cmdret 为 true,我想要将我的进程退出代码设置为 WTERMSIG(cmdret),以便 WIFSIGNALED 在我自己进程的退出代码上返回 true。

我该怎么做?假设我不想向自己的进程发送与子进程的致命信号相匹配的致命信号 - 如果子进程以 SIGABRTSIGSEGV 退出,我不希望向我的包装器发送中止或段错误信号。


glibc定义相关宏为

/* If WIFEXITED(STATUS), the low-order 8 bits of the status.  */
#define __WEXITSTATUS(status)   (((status) & 0xff00) >> 8)

/* If WIFSIGNALED(STATUS), the terminating signal.  */
#define __WTERMSIG(status)      ((status) & 0x7f)

/* If WIFSTOPPED(STATUS), the signal that stopped the child.  */
#define __WSTOPSIG(status)      __WEXITSTATUS(status)

/* Nonzero if STATUS indicates normal termination.  */
#define __WIFEXITED(status)     (__WTERMSIG(status) == 0)

/* Nonzero if STATUS indicates termination by a signal.  */
#define __WIFSIGNALED(status) \
  (((signed char) (((status) & 0x7f) + 1) >> 1) > 0)

exit(...)文档说:

The exit() function causes normal process termination and the least significant byte of status (i.e., status & 0xFF) is returned to the parent (see wait(2)).

类似_exit(...)返回status & 0xFFmain的返回值使用低8位正常退出代码。

shell convention就是使用小于125的退出码作为子进程退出,126为“已找到但不可执行”,127为“未找到”,128+N为“以信号N退出”。这是可行的,但要求调用者知道他们是否通过中间 shell 调用该进程,或者没有正确解释退出代码。

这使得无法区分本身以大于 125 的代码退出的进程与信号退出或包装器或 shell 失败。如果调用包装命令的命令在原始命令的返回代码上使用 WIFEXITEDWTERMSIG 等测试宏,则可能会中断这些命令。即使子进程收到信号退出,包装器也会显示为已正常退出。

我希望我的包装器对调用者完全透明,因此如果包装的进程依次退出并带有信号,则在包装器的返回代码上调用 WEXITSIG(ret) 将返回信号。

这可能吗?

最佳答案

如果您想在父级中复制子级的等待状态, 那么如果WIFEXITED(ws)返回true,可以 _exit(WEXITSTATUS(ws))如果 WIFSIGNALED(ws)返回true,你可以这样做signal(WTERMSIG(ws),SIG_DFL); raise(WTERMSIG(ws)); (即,在将其重置为默认配置后引发相同的信号,以便引发它肯定会终止进程)。

我不认为 Unix 内核会让你假装信号死亡而不实际经历信号死亡。如果您试图避免它以防止核心转储,那么您可以使用特定于平台的解决方案来仅为您的包装器进程禁用核心转储。例如,在 Linux 上,您可以调用 prctl(PR_SET_DUMPABLE,0); .

关于c - 退出时从子进程传播 WTERMSIG 退出代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76039949/

相关文章:

c - FOR 循环 : Finding value of pi using a series - absurd output

c++ - 在 C++ 中将静态数组声明为指针

c - 读取报告 Bad File Descriptor 尽管 getc 成功使用相同的 fd 读取 char

linux - 从操作系统接收 SIGTERM

c - posix 扩展正则表达式 : (()|abc)xyz 的预期行为

c - posix fork() & win32 CreateProcess() 之后的子进程名称是什么?

java - 保证TCP客户端和服务器之间不丢包

unix - 隐藏来自 ps 的参数

unix - 创建给定大小的 gzip block (填充)

c - putwchar/getwchar 编码?