// The nohup program seems to let things kill its kids in fedora 20. // This program will endeavor to eradicate whatever is leaking through // nohup. #include #include #include #include #include #include #include #include int bastards[] = { SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGFPE, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 }; #ifdef DO_DEBUG #define DBPRINTF(args) \ { \ FILE * dbf = fopen("/home/tom/dammit.log", "a"); \ fprintf args; \ fclose(dbf); \ } #else #define DBPRINTF(args) #endif int main(int argc, char ** argv) { // Make everything point to /dev/null, close all other file descriptors int null_out_fd = open("/dev/null", O_WRONLY); int null_in_fd = open("/dev/null", O_RDONLY); dup2(null_out_fd, fileno(stdout)); dup2(null_out_fd, fileno(stderr)); dup2(null_in_fd, fileno(stdin)); for (int i = 3; i < 60000; ++i) { close(i); } // Ignore every ignorable signal struct sigaction act; for (int i = 0; i < sizeof(bastards)/sizeof(bastards[0]); ++i) { memset((void *)&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; sigaction(bastards[i], &act, NULL); } // Fork a child we can make into a new session pid_t kid = fork(); if (kid == 0) { // This is the child. Make a new session here. pid_t s = setsid(); DBPRINTF((dbf,"1st setsid call returns %d\n",(int)s)) // Now fork yet another child to do all the real work and make // the intermediate child exit. pid_t grandkid = fork(); if (grandkid == 0) { s = setsid(); // Just to make doubly sure. DBPRINTF((dbf,"2nd setsid call returns %d\n",(int)s)) ++argv; --argc; execvp(argv[0], argv); DBPRINTF((dbf,"Oops. Executed past the exec of %s\n",argv[0])) _exit(2); } else { _exit(0); } } else { // This is the parent, wait for the kid. int status; waitpid(kid, &status, 0); } return 0; }