Installing SIGTSTP Foreground Process

江枫思渺然 提交于 2020-01-02 10:18:30

问题


I am trying to install a CTRL-Z (SIGTSTP) handler for a running foreground process.

I set the handler (sigaction) right before I wait in the parent. Is this the right place? It doesn't seem to work right..

EDIT:

I am writing a shell. Here is an outline of how my code looks like. I currently set the handler in the parent as shown below (which doesn't seem to work).

// input from user for command to run
pid_t pid;
pid = fork();

// Child Process
if (pid == 0) {
    // handle child stuff here
    // exec() etc...
}

else if (pid < 0)
    // error stuff

/* Parent Here */
else {
    // Give process terminal access
    // SET HANDLER FOR SIGTSTP HERE???
    wait()
    // Restore terminal access
}

回答1:


You are doing things complete wrong.

You DON'T send SIGTSTP to child process, the tty send SIGTSTP to child process DIRECTLY.

Try

$ stty -a
speed 38400 baud; rows 55; columns 204; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

Notice:

susp = ^Z;

that tells the tty how to deal with "CTRL-Z", when the tty gets ^Z it sends SIGTSTP signal to all process in the current foreground process group

How to handle process group

When you launch a new process in the shell, before execvX, put the new process into a new process group, then call tcsetpgrp to set the new process group foreground. So any future signal will send to the child process directly. if the child forks new process, they will be in the same process group; so the entire process group will be suspended when ^Z is pressed.

pid = fork()
if (pid) {
  // parent
  setpgid(pid, pid); // put child into a new process group
  int status;
  wait(pid, &status, 0);
} else {
  // child
  pid = getpid();
  setpgid(pid, pid);
  if (isatty(0)) tcsetpgrp(0, pid);
  if (isatty(1)) tcsetpgrp(1, pid);
  if (isatty(2)) tcsetpgrp(2, pid);
  execvX ...
}

Once any signal comes from tty causing child processes stop/term/exit your shell will return from wait, check status to know what happened to the child.

Prevent your shell from stopping

Your shell should mask SIGTSTP signal, because shell do not suspend. You do this at the beginning, when you start the shell. but don't forget fork will derive sigmask, so you need to enable SIGTSTP after fork in the child process.




回答2:


To handle a SIGTSTP to the child, this is needed after waitpid:

if (WIFSTOPPED(status)) {
    printf("Child received SIGTSTP");
}


来源:https://stackoverflow.com/questions/9853921/installing-sigtstp-foreground-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!