我正在尝试在迷你C Shell中实现Ctrl+Z
的行为。我的代码当前接收到SIGTSTP
信号并正确地挂起了该进程,但是我似乎无法让它移到后台并将shell进程放回前台。
我已经尽力更改了挂起的子进程组,以便我的waitpid()
循环可以继续进行(因为waitpid(-1, ...)
应该只找到与父进程组相同的子进程,对吗?),但是它总是卡住,等待挂起的进程结束。
while循环到达打印Continuing
的地步,然后waitpid()
永远不会结束,除非我从外部终止子进程。
Ctrl+C
工作正常。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <string.h>
int main()
{
char inbuf[256];
pid_t pid;
struct sigaction act;
for ( ; ; )
{
tcsetpgrp(fileno(stdin), getpgrp());
act.sa_handler = SIG_IGN;
assert(sigaction(SIGINT, &act, NULL) == 0);
assert(sigaction(SIGTSTP, &act, NULL) == 0);
printf("> ");
gets(inbuf);
pid = fork();
switch (pid)
{
case -1:// error
perror("fork");
exit(EXIT_FAILURE);
break;
case 0: // child
setpgrp();
tcsetpgrp(fileno(stdin), getpgid(pid));
act.sa_handler = SIG_DFL;
assert(sigaction(SIGINT, &act, NULL) == 0);
assert(sigaction(SIGTSTP, &act, NULL) == 0);
execlp( inbuf, inbuf, (char *)0 );
printf("execlp failed\n");
exit(EXIT_FAILURE);
break;
default:// parent
setpgid(pid, pid);
int status = 0;
signal(SIGTTOU, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
tcsetpgrp(fileno(stdin), getpgid(pid));
int parent_group = getpgid(pid);
while (1) {
pid = waitpid(-1, &status, WUNTRACED);
printf("PID: %d\n", pid);
if (pid < 1) {
printf("Breaking\n");
break;
}
if (WIFSTOPPED(status)) {
printf("STOPPED: %d!\n", pid);
// I feel like I should be sending the process, pid, to the background here
//tcsetpgrp(fileno(stdin), parent_group);
//setpgid(pid, pid);
}
printf("Continuing\n");
}
}
memset(inbuf, '\0', sizeof(inbuf));
}
return 0;
}