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);
}
12
  • Why not ps for PPID?
    – user147505
    Feb 28, 2018 at 18:31
  • because that would require polling, right? Feb 28, 2018 at 18:32
  • And what's the problem with that? Put it in your question.
    – user147505
    Feb 28, 2018 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 Feb 28, 2018 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) Feb 28, 2018 at 18:44

1 Answer 1

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.