1

I have a detached child process. It knows its parent's pid. Is there some way on both MacOS and Linux that I can listen for when the parent process exits, from the child process?

I need to make a call to delete a lockfile from the child, when the parent process dies.

I am looking for a solution that does not require polling.

I heard that waitid() might do it. I have this small program that compiles on MacOS with gcc, but it exits with code 255 - my only guess is that this is because waitid() won't work with processes that aren't child process of the current process?

#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    pid_t pid = atoi(argv[1]);
    printf("pid = %jd\n", (intmax_t) pid);
    siginfo_t sig;
    return waitid(P_PID, pid, &sig, WEXITED|WNOWAIT);
}
  • Why not ps for PPID? – Tomasz Feb 28 '18 at 18:31
  • because that would require polling, right? – Alexander Mills Feb 28 '18 at 18:32
  • And what's the problem with that? Put it in your question. – Tomasz Feb 28 '18 at 18:34
  • Yeah I am looking for a solution that does not require polling, I will put that in the question - if 100s of programs on your machine use polling, it just causes performance degradation - it's like polluting right – Alexander Mills Feb 28 '18 at 18:35
  • 2
    You could create a pipe before forking, close the reading end in the parent, the writing end in the child and have the child use select()/poll()/read() to detect the pipe going away when the parent dies (which would cause the writing end of the pipe to be closed, and read() to return for instance) – Stéphane Chazelas Feb 28 '18 at 18:44
0

On MacOS, the following actually has the behavior I am looking for (and possibly doesn't use polling?)

https://github.com/brainopener/mac-pid-waiter

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/event.h>

int main(int argc, const char * argv[]) {

    pid_t pid;    
    if(argc!=2 || (pid=atoi(argv[1]))<=0)
    {
        fprintf(stderr,"USAGE\nwaiter pid\n");
        return 1;
    }

    int kq=kqueue();
    if (kq == -1) {
        fprintf(stderr,"kqueue returned -1.");
    return 1;
    }

    struct kevent ke;    
    EV_SET(&ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);

    if (kevent(kq, &ke, 1, NULL, 0, NULL)<0) {
        fprintf(stderr,"kevent failed.");
    return 1;
    }


    for(;;) {
        memset(&ke,0,sizeof(struct kevent));
        if(kevent(kq, NULL, 0, &ke, 1, NULL)<0){
            fprintf(stderr,"kevent failed.");
        return 1;
        }

        if (ke.fflags & NOTE_EXIT)
        break;
    }

    return 0;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.