c - 如果孩子没有状态变化,如何取消waitpid?
问题描述
免责声明:C 中的绝对新手,我以前主要使用 Java。
在许多 C 初学者教程中,waitpid
在进程管理示例中使用它来等待其子进程完成(或使用类似的选项进行状态更改WUNTRACED
)。但是,如果没有发生此类状态更改,无论是通过直接用户输入还是编程(例如超时),我都找不到有关如何继续的任何信息。那么有什么好的撤消方法waitpid
呢?类似于SIGCONT
停止的进程,而是延迟的进程waitpid
。
或者,如果这个想法没有意义,知道为什么会很有趣。
解决方案
如果我建议使用alarm()
呢?在倒计时结束后alarm()
交付(有关更多详细信息,请参见手册页)。但是从手册页来看,默认处置是终止进程。因此,您需要注册一个信号处理程序来处理. 代码如下...SIGALRM
alarm()
signals
SIGALRM
SIGALRM
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void sigalrm(int signo)
{
return; // Do nothing !
}
int main()
{
struct sigaction act, oldact;
act.sa_handler = sigalrm; // Set the signal handler
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT // If interrupt defined set it to prevent the auto restart of sys-call
act.sa_flags |= SA_INTERRUPT;
#endif
sigaction(SIGALRM, &act, &oldact);
pid_t fk_return = fork();
if (fk_return == 0) { // Child never returns
for( ; ; );
}
unsigned int wait_sec = 5;
alarm(wait_sec); // Request for SIGALRM
time_t start = time(NULL);
waitpid(-1, NULL, 0);
int tmp_errno = errno; // save the errno state, it may be modified in between function calls.
time_t end = time(NULL);
alarm(0); // Clear a pending alarm
sigaction(SIGALRM, &oldact, NULL);
if (tmp_errno == EINTR) {
printf("Child Timeout, waited for %d sec\n", end - start);
kill(fk_return, SIGINT);
exit(1);
}
else if (tmp_errno != 0) // Some other fatal error
exit(1);
/* Proceed further */
return 0;
}
输出
Child Timeout, waited for 5 sec
注意:您不必担心,SIGCHLD
因为它的默认处置是忽略。
编辑
为了完整起见,保证SIGALRM
不会交付给孩子。这是来自的手册页alarm()
由 alarm() 创建的警报在 execve(2) 中保留,不会被通过 fork(2) 创建的子级继承。
编辑 2
我不知道为什么一开始它没有打动我。一种简单的方法是阻止SIGCHLD
并调用sigtimedwait()
支持超时选项的方法。代码是这样的......
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigmask, NULL);
pid_t fk_return = fork();
if (fk_return == 0) { // Child never returns
for( ; ; );
}
if (sigtimedwait(&sigmask, NULL, &((struct timespec){5, 0})) < 0) {
if (errno == EAGAIN) {
printf("Timeout\n");
kill(fk_return, SIGINT);
exit(1);
}
}
waitpid(fk_return, NULL, 0); // Child should have terminated by now.
/* Proceed further */
return 0;
}
输出
Timeout
推荐阅读
- python - k-armed Bandit 问题的 GPU 优化
- node.js - 如何在本机反应中更新 API 响应中的折线图值
- javascript - 如何让屏幕阅读器在表格内容更改时阅读通知?
- python - 循环遍历多个 panda 数据帧以在 Python 中获取多个数据帧输出
- windows - 如何获得子进程的句柄 uintptr?
- javascript - (节点:2136)UnhandledPromiseRejectionWarning:TypeError:浏览器
- c - C语言中排序函数的使用方法
- javascript - 在主要操作 DOM 元素时,在 JS 中是否有任何 Pattern 或 Class 样式可以遵循?
- c# - 使用 ColorMatrix 将图像转换为单色
- javascript - Greasemonkey (Violentmonkey) 脚本更改网站值