#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& はブロックしません。
コードを見なければ、どこに問題があるかを知ることは不可能です。ただし、ゾンビ プロセスの処理方法に注意してください。pid を追跡する必要がないように、sa_flags で SA_NOCLDWAIT を使用します。また、waitpid() を使用してフォアグラウンドの子プロセスを待ちます。そして、そこが問題だと思います。コードが waitpid() ではなく wait() を呼び出している可能性があります。違いは、wait() がすべての子を待機することです。