views:

201

answers:

3

I do the usual fork + exec combination:

int sockets [2];
socketpair (AF_LOCAL, SOCK_STREAM, 0, sockets);
int pid = fork ();

if (pid == 0) {
  // child
  dup2 (sockets[0], STDIN_FILENO);
  dup2 (sockets[0], STDOUT_FILENO);
  execvp (argv[0], argv);
  _exit (123);
}
// parent

close (sockets[0]);
// TODO wait and see if child crashes

Is it possible to wait until child crashes or begins waiting on read(...)?

A: 

Here's a suggestsion:

Open a pipe, the child process can send a message down the pipe to tell the parent that it is about to read() on stdin. If you do this correctly and the child dies, the parent will be notified that the pipe has been broken, I think.

Artelius
The child is going to call arbitrary command. I don't have control over its source.
Łukasz Lew
I don't know if there is any easy solution, then. You could run the child in `strace` or something similar to see the system calls it uses...
Artelius
+1  A: 

checkout waitpid

 pid_t waitpid(pid_t pid, int *stat_loc, int options);

from

#include <sys/wait.h>
Charles Ma
How does it help?
Łukasz Lew
it'll help you figure out when it has crashed, but detecting when it's waiting for input is trickier...
Charles Ma
+1  A: 

You can use the ptrace(2) syscall to do what strace(1) does. In the child process, before exec'ing, you'll need to invoke PTRACE_TRACEME, and that will attach the parent process to it as a debugger. The parent will then have to resume execution with PTRACE_SYSCALL, and it will stop at each syscall. The parent should use wait(2) to wait until the child trips at a syscall, then use ptrace with PTRACE_PEEK* to examine the arguments to the syscall. Repeat that until the syscall you're waiting for (read) is invoked, then detach from the child process with PTRACE_DETACH. Look at the source of strace for details on how to recognize the syscall of interest. If the process crashes, the wait syscall will tell you that the process got SIGSEGV. Don't forget to detach in that case, too.

Alexey Feldgendler