unix 在退出时从子进程传播WTERMSIG退出代码

dy2hfwbg  于 2023-04-20  发布在  Unix
关注(0)|答案(2)|浏览(287)

我正在编写一个 Package 器命令,它调用一个子进程,等待它退出,并传播它的退出代码。
我想将子进程的退出状态传播到我自己的进程的退出代码 *,即使子进程退出时带有信号 *。如果WIFSIGNALED(cmdret)对于包含waitpid(...)调用或类似调用结果的某些int cmdret为true,我想将我的进程退出代码设置为WTERMSIG(cmdret),以便WIFSIGNALED在我自己的进程退出代码上返回true。
我不想给自己的进程发送一个与子进程匹配的致命信号-如果子进程以SIGABRTSIGSEGV退出,我不想给我的 Package 器发送一个abort或segfault信号。
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(...)文档说:
exit()函数导致正常进程终止,并将status的最低有效字节(即status & 0xFF)返回给父进程(参见wait(2))。
类似地,_exit(...)返回status & 0xFF,并且来自main的返回值使用低8位作为正常退出代码。
shell convention是使用小于125的子进程退出退出代码,126表示“找到但不可执行”,127表示“未找到”,128+N表示“以信号N退出”。这可以工作,但需要调用者知道他们是否通过中间shell调用进程以正确解释退出代码。
这使得无法区分自己以大于125的代码退出的进程和 Package 器或shell的信号退出或失败。如果它们在原始命令的返回代码上使用WIFEXITEDWTERMSIG等测试宏,则可能会中断调用 Package 命令的命令。即使子进程在信号退出时, Package 器也会显示为正常退出。
我希望我的 Package 器对调用者是完全透明的,因此如果 Package 的进程退出时返回一个信号,那么在 Package 器的返回代码上调用WEXITSIG(ret)将返回信号。
这有可能吗

sdnqo3pr

sdnqo3pr1#

如果你想在父进程中复制子进程的等待状态,那么如果WIFEXITED(ws)返回true,你可以执行_exit(WEXITSTATUS(ws)),如果WIFSIGNALED(ws)返回true,你可以执行signal(WTERMSIG(ws),SIG_DFL); raise(WTERMSIG(ws));(也就是说,在将其重置为默认配置后引发相同的信号,这样引发它肯定会杀死进程)。
我不认为Unix内核会让你在没有真正经历信号死亡的情况下假装信号死亡。如果你试图避免它来防止核心转储,那么你可以使用特定于平台的解决方案来禁用核心转储,只是为了你的 Package 进程。例如,在Linux上,你可以调用prctl(PR_SET_DUMPABLE,0);

ktca8awb

ktca8awb2#

如果WIFSIGNALED(cmdret)对于包含waitpid(...)调用或类似调用的结果的某个int cmdret为true,我想将我的进程退出代码设置为WTERMSIG(cmdret),这样WIFSIGNALED将在我自己的进程退出代码上返回true。
不能。只能传播执行exit(2)调用的进程的退出代码。原因很简单。从wait(2)调用接收的结果代码是由内核生成的。它用您提供给exit(2)系统调用的退出代码填充退出代码,但你不能强迫其他的部分(退出代码只是值的最低有效8位)由内核填充,并且您无法控制在其中放入什么。这将伪造wait(2)系统调用,作为一个恶意(或损坏的)程序可能放置关于正确退出但被通知接收信号或转储核心映像的进程的不正确信息。退出代码是用户提供的唯一信息,你想怎么处理都行(像传播甚至欺骗它)这不会影响最终状态(当然如果你死于中断,你不能传递退出代码)

相关问题