Linux daemon - zabicie procesów potomnych

0

Mam prostego daemon'a linux'owego. Który standardowo, robi forka, ubija proces rodzica, robi chroota, zamyka deskryptory itd.
Id procesu daemona zapisuje do /var/run/mydaemon.pid.

W kodzie właściwym programu, będę otwierał sobie kolejne wątki.
Problem polega na tym, że gdy chcę zrobić kill -9 lub kill -15 na procesie mydaemon.pid to nie ubija mi wątków, które sobie utworzyłem. Myślę, że jest to związane z tym, że na początku ubiłem proces rodzica (zdemonizowałem program).

Jak ubić te procesy mająć tylko PID procesu daemon'a ?

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

void signal_handler(int sig) {
    switch(sig) {
        case SIGHUP:
            syslog(LOG_WARNING, "Received SIGHUP signal.");
        break;

        case SIGTERM:
            syslog(LOG_WARNING, "Received SIGTERM signal.");
            // TODO: Zamknięcie dzieci ?
            exit(EXIT_SUCCESS);
        break;
        default:
            syslog(LOG_WARNING, "Unhandled signal %s", strsignal(sig));
            break;
    }
}

int main() {
    signal(SIGHUP, signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGINT, signal_handler);
    signal(SIGQUIT, signal_handler);

    syslog(LOG_INFO, "%s daemon starting up", "MyDaemon");

    pid_t pid, sid;
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }

    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    const char pidflie [] = "/var/run/mydaemon.pid";
    FILE * pidfp = fopen(pidflie, "w");
    if(pidfp == NULL) {
        fprintf(stderr, "Can't write to file %s\n", pidflie);
        exit(EXIT_FAILURE);
    }
    fprintf(pidfp, "%d", getpid());
    fclose(pidfp);

    sid = setsid();
    if (sid < 0) {
        fprintf(stderr, "Cannot create a new SID for the child process\n");
        exit(EXIT_FAILURE);
    }

    const char root [] = "/tmp";
    if(chroot(root) < 0) {
        fprintf(stderr, "Cannot change the root directory %s\n", root);
        exit(EXIT_FAILURE);
    }

    if ((chdir("/")) < 0) {
        fprintf(stderr, "Change the current working directory '/'\n");
        exit(EXIT_FAILURE);
    }

    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    if (fork() == 0) {
        // Dziecko
        while (1) {
           sleep(30);
        }
    } else {
        // Rodzic
        while (1) {
           sleep(30);
        }
    }
    return 0;
}
 
ps aux | grep linuxdaemon
root     13008  0.0  0.0  11864   412 ?        Ss   14:19   0:00 ./linuxdaemon
root     13009  0.0  0.0  11864   256 ?        S    14:19   0:00 ./linuxdaemon
cat /var/run/mydaemon.pid 
13008
kill -9 13008
ps aux | grep linuxdaemon
root     13009  0.0  0.0  11864   256 ?        S    14:19   0:00 ./linuxdaemon

Jeśli chodzi o SIGTERM to mogę zrobić handler, ale SIGKILL nie można przechwycić :/
Chcę, żeby proces 13009 również się ubił po ubicu 13008. Jak to zrobić?

0

Ok, udało mi się rozwiązać problem.
Najprościej będzie w procesie dziecka, sprawdzić id procesu rodzica. Jeżeli proces rodzica zostanie ubity to jego dziecko stanie się rodzicem a jego PPID będzie równy 1 (czyli będzie dzieckiem procesu int, który zbiera nie przydzielone procesy), wtedy ubijamy siebie samego.

if(getppid() == 1) { 
    exit(EXIT_FAILURE);
} 

Cały kod:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

void signal_handler(int sig) {
    switch(sig) {
        case SIGHUP:
            syslog(LOG_WARNING, "Received SIGHUP signal.");
        break;

        case SIGTERM:
            syslog(LOG_WARNING, "Received SIGTERM signal.");
            exit(EXIT_SUCCESS);
        break;
        default:
            syslog(LOG_WARNING, "Unhandled signal %s", strsignal(sig));
            break;
    }
}

int main() {
    signal(SIGHUP, signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGINT, signal_handler);
    signal(SIGQUIT, signal_handler);

    syslog(LOG_INFO, "%s daemon starting up", "MyDaemon");

    pid_t pid, sid;
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }

    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    const char pidflie [] = "/var/run/mydaemon.pid";
    FILE * pidfp = fopen(pidflie, "w");
    if(pidfp == NULL) {
        fprintf(stderr, "Can't write to file %s\n", pidflie);
        exit(EXIT_FAILURE);
    }
    fprintf(pidfp, "%d", getpid());
    fclose(pidfp);

    sid = setsid();
    if (sid < 0) {
        fprintf(stderr, "Cannot create a new SID for the child process\n");
        exit(EXIT_FAILURE);
    }

    const char root [] = "/tmp";
    if(chroot(root) < 0) {
        fprintf(stderr, "Cannot change the root directory %s\n", root);
        exit(EXIT_FAILURE);
    }

    if ((chdir("/")) < 0) {
        fprintf(stderr, "Change the current working directory '/'\n");
        exit(EXIT_FAILURE);
    }

    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    if (fork() == 0) {
        // Dziecko
        while (1) {
            if(getppid() == 1) {
                exit(EXIT_FAILURE);
            }
            sleep(30);
        }
    } else {
        // Rodzic
        while (1) {
           sleep(30);
        }
    }
    return 0;
}
 

1 użytkowników online, w tym zalogowanych: 0, gości: 1