Демон не останавливается в Linux - PullRequest
3 голосов
/ 15 ноября 2010

Я использовал следующее руководство (http://peterlombardo.wikidot.com/linux-daemon-in-c), и оно работает прекрасно и красиво, прими, что это не убьет.

main.cpp

//Global Directives
//#define DEBUG 1
#define DAE_NAME "dae"
#define DAE_PID "/var/run/dae.pid"

//Includes
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <fstream>
#include <iomanip>
#include <vector>
#include <syslog.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>

//Namespace (System)
using namespace std;

//Classes
#include "class.h"

//Structures
#include "struct/struct.h"

//Functions
#include "function/signal_handler.h"

void usage(int argc, char *argv[]) {
    if (argc >=1) {
        printf("Usage: %s -h -nn", argv[0]);
        printf("  Options:n");
        printf("      -ntDon't fork off as a daemon.n");
        printf("      -htShow this help screen.n");
        printf("n");
    }
}

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

#if defined(DEBUG)
    int daemonize = 0;
#else
    int daemonize = 1;
#endif

    // Setup signal handling before we start
    signal(SIGHUP, signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGINT, signal_handler);
    signal(SIGQUIT, signal_handler);

    //Print Usage Information
    int c;
    while((c = getopt(argc, argv, "nh|help")) != -1) {
        switch(c){
            case 'h':
             usage(argc, argv);
                exit(0);
                break;
            case 'n':
                daemonize = 0;
                break;
            default:
             usage(argc, argv);
                exit(0);
                break;
        }
    }

    // Setup syslog logging
#if defined(DEBUG)
    setlogmask(LOG_UPTO(LOG_DEBUG));
    openlog(DAE_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
#else
    setlogmask(LOG_UPTO(LOG_INFO));
    openlog(DAE_NAME, LOG_CONS, LOG_USER);
#endif

    //------------
    //Daemon Setup
    //------------
    pid_t pid, sid;

    if (daemonize) {
        syslog(LOG_INFO, "Starting %s", DAE_NAME);

        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
            exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then
           we can exit the parent process. */
        if (pid > 0) {
            exit(EXIT_SUCCESS);
        }

        /* Change the file mode mask */
        umask(0);

        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
            /* Log the failure */
            exit(EXIT_FAILURE);
        }

        /* Change the current working directory */
        if ((chdir("/")) < 0) {
            /* Log the failure */
            exit(EXIT_FAILURE);
        }

        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
    }

    int count = 1;

    //-------
    //Process
    //-------
    while (1){
        process();

        syslog (LOG_INFO, "%s Processed(%s, %d)", DAE_NAME, getlogin(), count);

        count++;
    }

    syslog (LOG_INFO, "Exiting Daemon %s", DAE_NAME);

    closelog (); //Close the Connection

    exit(EXIT_SUCCESS);
}

singal_handler.h

#ifndef SIGNAL_HANDLER_H_
#define SIGNAL_HANDLER_H_

void signal_handler(int sig) {

    switch(sig) {
        case SIGHUP:
            syslog(LOG_WARNING, "Received SIGHUP signal.", DAE_NAME);
            break;
        case SIGTERM:
            syslog(LOG_WARNING, "Received SIGTERM signal.", DAE_NAME);
            break;
        default:
            syslog(LOG_WARNING, "Unhandled signal ", DAE_NAME);
            break;
    }
}

#endif

Командная строка

Итак, в командной строке я запускаю этот

. / Дэ

А потом я бегу

kill procid

Журналы

INFROMATIONAL, Начиная с dae

ИНФОРМАЦИЯ, обработано (ноль), 1)

ИНФОРМАЦИЯ, обработано (ноль), 2)

ИНФОРМАЦИОННО, обработано (ноль), 3)

ПРЕДУПРЕЖДЕНИЕ, принят сигнал SIGTERM.

ИНФОРМАЦИОННО, ДА Обработано ((ноль), 4)

ИНФОРМАЦИОННЫЙ, обработано (ноль), 5)

Чертова вещь не останавливается? Любые идеи спасибо

1 Ответ

5 голосов
/ 15 ноября 2010

Поскольку вы обрабатываете сигнал TERM , его поведение по умолчанию отключено.

Вам необходимо явно вызвать exit () из вашего обработчика сигнала для вашегопрограмма для завершения.

Вот реализация, которая позволяет выполнять очистку и не использует atexit () :

signal_handler.h

#ifndef SIGNAL_HANDLER_H_
#define SIGNAL_HANDLER_H_

extern bool g_terminated;

void signal_handler(int sig) {

    switch(sig) {
        case SIGHUP:
            syslog(LOG_WARNING, "Received SIGHUP signal.", DAE_NAME);
            break;
        case SIGTERM:
            syslog(LOG_WARNING, "Received SIGTERM signal.", DAE_NAME);
            g_terminated = true;
            break;
        default:
            syslog(LOG_WARNING, "Unhandled signal ", DAE_NAME);
            break;
    }
}

#endif

main.cpp

bool g_terminated = false;

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

    //-------
    //Process
    //-------
    while (!g_terminated) {
        process();

        syslog (LOG_INFO, "%s Processed(%s, %d)", DAE_NAME, getlogin(), count);

        count++;
    }

    // Cleanup...

    exit(EXIT_SUCCESS);
}
...