How can I get the PID of a new process before it executes?

335 views Asked by At

So that I can do some injecting and interposing using the inject_and_interpose code, I need to way to get the PID of a newly-launched process (a typical closed-source user application) before it actually executes.

To be clear, I need to do better than just "notice it quickly"--I can't be polling, or receiving some asynchronous notification that means that the process has already been executing for a few milliseconds by the time I take action.

I need to have a chance to do my injecting and interposing before a single statement executes.

I'm open to writing a background process that gets synchronously notified when a process by a particular name comes into existence. I'm also open to writing a launcher application that in turn fires up the target application.

Any solution needs to support 64-bit code, at a minimum, under 10.5 (Leopard) through 10.8 (Mountain Lion).

In case this proves to be painfully simple, I'll go ahead and admit that I'm new to OS X :) Thanks!

1

There are 1 answers

7
Jonathon Reinhart On

I know how to do this on Linux, so maybe it would be the same(-ish) on OSX.

You first call fork() to duplicate your process. The return value of fork() indicates whether you are the parent or child. The parent gets the pid of the child process, and the child gets zero.

So then, the child calls exec() to actually begin executing the new executable. With the use of a pipe created before the call to fork, the child could wait on the parent to do whatever it needed before execing the new execuatable.

pid_t pid = fork();
if (pid == -1) {
    perror("fork");
    exit(1);
}
if (pid > 0) {
    // I am the parent, and pid is the PID of the child process.

    //TODO: If desired, somehow notify child to proceed with exec
}
else {
    // I am the child.

    //TODO: If desired, wait no notification from parent to continue

    execl("path/to/executable", "executable", "arg1", NULL);

    // Should never get here.
    fprintf(stderr, "ERROR: execl failed!\n");  
}