我正在编写一个包装器命令,该命令调用子进程、等待其退出并传播其退出代码。足够简单。
我想将子进程的退出状态传播到我自己进程的退出代码即使子进程通过信号退出。如果 WIFSIGNALED(cmdret)
对于某些包含 waitpid(...)
调用或类似调用结果的 int cmdret
为 true,我想要将我的进程退出代码设置为 WTERMSIG(cmdret)
,以便 WIFSIGNALED
在我自己进程的退出代码上返回 true。
我该怎么做?假设我不想向自己的进程发送与子进程的致命信号相匹配的致命信号 - 如果子进程以 SIGABRT
或 SIGSEGV
退出,我不希望向我的包装器发送中止或段错误信号。
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 ofstatus
(i.e.,status & 0xFF
) is returned to the parent (seewait(2)
).
类似_exit(...)
返回status & 0xFF
,main
的返回值使用低8位正常退出代码。
shell convention就是使用小于125的退出码作为子进程退出,126为“已找到但不可执行”,127为“未找到”,128+N为“以信号N退出”。这是可行的,但要求调用者知道他们是否通过中间 shell 调用该进程,或者没有正确解释退出代码。
这使得无法区分本身以大于 125 的代码退出的进程与信号退出或包装器或 shell 失败。如果调用包装命令的命令在原始命令的返回代码上使用 WIFEXITED
、WTERMSIG
等测试宏,则可能会中断这些命令。即使子进程收到信号退出,包装器也会显示为已正常退出。
我希望我的包装器对调用者完全透明,因此如果包装的进程依次退出并带有信号,则在包装器的返回代码上调用 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/