SIGTSTP信号没有阻止孩子?

时间:2016-12-07 23:23:27

标签: c++ signals fork exec

我正在尝试编写一个分叉的程序,子程序执行命令然后将控制权返回给父程序。我无法让SIGTSTP(Cz)信号按预期工作,但是......我希望父母忽略它,但是孩子要停止并将控制权交还给父母,这样以后孩子就可以恢复或杀死(使用内置命令)。我将相关代码分离成一个较小的程序只是为了测试它,看起来像A)孩子在输入Cz时没有停止,或者B)它确实停止了,但是没有将控制权返回给父母(我是倾向于此,因为当我使用cat作为标准输入时,它在Cz之后表现不同。这是我的代码。

#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;
}

1 个答案:

答案 0 :(得分: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()的必要选项。