Использование Ctrl + Z для создания фона процесса в C Shell - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь реализовать поведение Ctrl+Z в оболочке mini C.Мой код в настоящее время получает сигнал SIGTSTP и корректно приостанавливает процесс, однако я не могу заставить его переместиться в фоновый режим и вернуть процесс оболочки обратно на передний план.

Я старался изо всех силизменить группу процессов дочернего процесса, который приостановлен, чтобы мой цикл 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...