2016-12-07 3 views
2

Я пытаюсь написать программу, которая вилки, ребенок выполняет команду, а затем возвращает управление родительскому. У меня возникли проблемы с получением сигнала SIGTSTP (Cz) для работы по назначению, хотя ... Я хочу, чтобы родитель проигнорировал его, но ребенок остановил и вернул управление родительскому объекту, так что потом ребенок может быть возобновлен или убит (с встроенной командой). Я выделил соответствующий код в меньшую программу, чтобы проверить его, и кажется, что A) ребенок не останавливается при вводе Cz, или B) он останавливается, но не возвращает управление родительскому (я опираясь на это, потому что, когда я использую cat для stdin, он ведет себя по-разному после Cz). Вот мой код.Сигнал SIGTSTP не останавливает ребенка?

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <fcntl.h> 
#include <cstring> 
#include <unistd.h> 
#include <cstdlib> 
#include <iostream> 
#include <vector> 
#include <string> 
#include <signal.h> 


int main(){ 
    std::cout.setf(std::ios::unitbuf); 

    std::vector<std::string> vec; vec.push_back("cat"); 
    std::vector<char*> chvec; 
    for(unsigned int i = 0; i < vec.size(); i++){ 
    chvec.push_back(&vec[i][0]); 
    } 
    chvec.push_back(NULL); 
    vec.erase(vec.begin(), vec.begin() + chvec.size()); 

    char** argv = &chvec[0]; 
    signal(SIGTSTP,SIG_IGN); 

    pid_t pid; 
    if((pid = fork()) == 0){ 
    signal(SIGTSTP,SIG_DFL); 
    /*pid = getpid(); 
    setpgid(pid,pid);*/ 
    std::cout << "before exec" << std::endl; 
    execvp(argv[0],argv); 
    perror("exec"); 
    } 
    else{ 
    //setpgid(pid,pid); 
    int status; 
    waitpid(pid,&status,0); 
    if(WIFEXITED(status) || WIFSIGNALED(status)){ 
     std::cout << "exited or signaled" << std::endl; 
    } 
    if(WIFSTOPPED(status)){ 
     std::cout << "process stopped" << std::endl; 
    } 
    //std::cout << "process exited" << std::endl; 
    pause(); 
    } 
    return EXIT_SUCCESS; 
} 
+0

'chvec []' нужен конечный нулевой указатель. – Barmar

+0

исправлено, что (хотя оно ничего не влияет) – faezer

+0

Вы можете определить разницу между 'A' и' B', используя 'ps' в другом окне терминала. Если ребенок остановлен, он будет находиться в состоянии «T». – Barmar

ответ

1

Это было уже отмечено в комментариях, что вам нужно, чтобы исправить неопределенное поведение в результате vec вектора стирается. Это первая проблема.

Я вижу, что ваш код проверяет состояние выхода процесса, используя WIFSTOPPED.

Давайте review the documentation for the wait(2) system call, и посмотреть, что он говорит об этом:

WIFSTOPPED(wstatus) 
     returns true if the child process was stopped by delivery of a 
     signal; this is possible only if the call was done using WUN‐ 
     TRACED or when the child is being traced (see ptrace(2)). 

Таким образом, с этой информацией в стороны, после закрепления ранее упомянутых неопределенное поведение, и после изменения waitpid() вызова:

waitpid(pid,&status,WUNTRACED); 

Тогда я был в состоянии послать kill -TSTP <pid> сообщений породившей cat процесса, и получить ожидаемый

процесс остановлен

сообщение от тестовой программы.

P.S. Опираясь на дочерний процесс, я увидел, что дочерний процесс получает сигнал TSTP и останавливается просто отлично. Вопрос был просто в том, что родитель не обрабатывал его, без обязательной опции waitpid().

+0

О, черт возьми, я на самом деле пытался использовать WUNTRACED раньше, но вместо того, чтобы ждать сигнала остановки, кошка остановилась автоматически по какой-то причине (вместо ожидания C-z).Возможно, у меня был какой-то остаточный код из многих других вещей, которые я пробовал, это было бесполезно, но теперь это работает ... спасибо вам много! – faezer