![](/img/trans.png)
[英]C - Parent process waits indefinitely on forked child process running authopen
[英]Parent waits for previous child process on linux shell
我有一個程序可以派生一個進程,並確定子進程是否應該在前台和后台運行。 我在分叉之前調用信號函數來處理子信號,以確保死子進程不會變成僵屍。
到目前為止,我的程序運行良好,它會創建一個子進程,並在每當用戶輸入帶有“&”的命令時在后台運行它,並在每當用戶輸入不帶有“&”的命令時在前台運行它。
但是,我發現了一個非常有趣的行為。 假設我調用了以下操作序列:
sleep 5 &
ls
第一條命令可以正常工作,父進程無需等待睡眠5完成。 但是,當我運行“ ls”時,它將打印該文件夾中的所有文件(這很好),但是外殼卡住了,等待先前的“ sleep 5&”完成...
為什么會發生這種情況? 我的子進程和父進程(分叉后)的代碼如下所示:
if (pid == 0)
{
// child process, execute stuff
execv();
}
else if (pid > 0)
{
// parent process: call waitpid to wait for foreground child
}
我試圖做一些研究,但找不到任何可以幫助我的東西。 我嘗試通過在execv()之前調用子進程來使用“ set session-id”,但是它阻止了子進程在終端上打印任何內容。 任何幫助將不勝感激。 謝謝!
#define _XOPEN_SOURCE 700
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void run_command(void)
{
char *cmd = NULL, *arg;
size_t n, l;
bool background;
pid_t child;
l = getline(&cmd, &n, stdin);
cmd[l-1] = 0;
l--;
if (cmd[l-1] == '&') {
background = true;
cmd[l-1] = 0;
l--;
}
else
background = false;
arg = strchr(cmd, ' ');
if (arg) {
*arg = 0;
arg++;
}
child = fork();
if (child) {
if (!background)
waitpid(child, NULL, 0);
}
else {
execlp(cmd, cmd, arg, NULL);
exit(-1);
}
free(cmd);
}
int main(void)
{
sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sig.sa_handler = SIG_DFL;
sig.sa_mask = set;
sig.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sig, NULL);
while(!feof(stdin)) run_command();
}
這按預期工作:
hdante@aielwaste:~/code$ ./shell
pwd
/home/hdante/code
ls /home
hdante
sleep 5
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz
sleep 5&
xedit&
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz
在上面的示例中,sleep 5正確阻止,而sleep 5&和xedit&則沒有。
如果不查看代碼,就不可能知道問題出在哪里。 但是請注意我處理僵屍進程的方式:我在sa_flags中使用SA_NOCLDWAIT,因此不需要跟蹤pid。 另外,我等待使用waitpid()的前台子進程。 我認為這就是問題所在。 您的代碼可能正在調用wait()而不是waitpid()。 區別在於wait()等待所有的孩子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.