Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait() does not return after child received sigstop

Just as the title says, one process forks waits for its child to receive a SIGSTOP (self sent by the child) but it does not wake up after as if it didn't receive any SIGCHLD (but it actually did, tested with strace).

Anyone any ideas?

int main() {
  if (fork()) {
    wait(NULL);
    write(1, "Bye\n", 4);
  } else {
    kill(getpid(), SIGSTOP);
    write(1, "Hello\n", 6);
  }
return 0;
}

They both hang, whereas only the child should.

like image 968
ichigo663 Avatar asked Oct 10 '16 16:10

ichigo663


People also ask

What happens if you use wait () in the child?

Suspends the calling process until any one of its child processes ends. More precisely, wait() suspends the calling process until the system obtains status information on the ended child. If the system already has status information on a completed child process when wait() is called, wait() returns immediately.

What is the difference between wait () and waitpid ()?

Difference between wait and waitpid():Wait() waits for any child process but waitpid() waits for a specific child equal to pid. By default waitpid() waits for the only terminated child where as wait() waits for both terminated or a signaled child.

What does Waitpid () return?

Returned value If successful, waitpid() returns a value of the process (usually a child) whose status information has been obtained. If WNOHANG was given, and if there is at least one process (usually a child) whose status information is not available, waitpid() returns 0.

What does wait NULL return?

wait(NULL) will block the parent process until any of its children has finished. If the child terminates before the parent process reaches wait(NULL) then the child process turns to a zombie process until its parent waits on it and its released from memory.


1 Answers

The specification for wait says that it reports only children that have exited, not children that have stopped. You should use

waitpid(-1, 0, WUNTRACED);

instead.

The flag name WUNTRACED is a little cryptic - why isn't it WSTOPPED? This is a point where the standardized wait* API brushes up against the not-standardized ptrace API. Compare POSIX's definition of WUNTRACED

WUNTRACED
The status of any child processes specified by pid that are stopped, and whose status has not yet been reported since they stopped, shall also be reported to the requesting process.

… with its documentation in the Linux manpage …

WUNTRACED
also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.

So basically the default behavior of wait* has a special case embedded in it for the convenience of people writing debuggers (people writing debuggers will take every convenience they can get) and that special case has been around for so long that it affected the names chosen for waitpid's flags. (I don't know one way or the other, but I would not be surprised to learn that ptrace stops are older than job control stops.)

like image 106
zwol Avatar answered Nov 04 '22 14:11

zwol