summaryrefslogtreecommitdiffstats
path: root/src/Daemon/Daemon.cpp
blob: 0b7393aac795e13801ad4f2468404e10c6e3a6ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
    Copyright (C) 2009  Jiri Moskovcak (jmoskovc@redhat.com)
    Copyright (C) 2009  RedHat inc.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    */

#include "CrashWatcher.h"
#include "ABRTException.h"
#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

uint8_t sig_caught;

static void handle_fatal_signal(int signal)
{
    sig_caught = signal;
}

CCrashWatcher *g_pCrashWatcher = NULL;

void print_help()
{

}

int main(int argc, char** argv)
{
    int daemonize = 1;

    /* signal handlers */
    signal(SIGTERM, handle_fatal_signal);
    signal(SIGINT, handle_fatal_signal);

    try
    {
        if (argv[1])
        {
            if (strcmp(argv[1], "-d") == 0)
            {
                daemonize = 0;
            }
        }
        if (daemonize)
        {
            /* Open stdin to /dev/null. We do it before forking
             * in order to emit useful exitcode to the parent
             * if open fails */
            close(STDIN_FILENO);
            if (open("/dev/null", O_RDWR))
            {
                throw CABRTException(EXCEP_FATAL, "Can't open /dev/null");
            }
            /* forking to background */
            pid_t pid = fork();
            if (pid < 0)
            {
                throw CABRTException(EXCEP_FATAL, "CCrashWatcher::Daemonize(): Fork error");
            }
            if (pid > 0)
            {
                /* Parent */
                /* Wait for child to notify us via SIGTERM that it feels ok */
                int i = 20; /* 2 sec */
                while (sig_caught == 0 && --i)
                {
                        usleep(100 * 1000);
                }
                _exit(sig_caught != SIGTERM); /* TERM:ok (0), anything else: bad (1) */
            }
            /* Child (daemon) continues */
            pid_t sid = setsid();
            if(sid == -1)
            {
                throw CABRTException(EXCEP_FATAL, "CCrashWatcher::Daemonize(): setsid failed");
            }
            /* We must not leave fds 0,1,2 closed.
             * Otherwise fprintf(stderr) dumps messages into random fds, etc. */
            close(STDOUT_FILENO);
            close(STDERR_FILENO);
            dup(0);
            dup(0);
        }
        g_pCrashWatcher = new CCrashWatcher(DEBUG_DUMPS_DIR);
        if (daemonize)
        {
            /* Let parent know we initialized ok */
            kill(getppid(), SIGTERM);
        }
        g_pCrashWatcher->Run();
    }
    catch(CABRTException& e)
    {
        std::cerr << "Cannot create daemon: " << e.what() << std::endl;
    }
    catch(std::exception& e)
    {
        std::cerr << "Cannot create daemon: " << e.what() << std::endl;
    }

    delete g_pCrashWatcher;

    /* Take care to emit correct exit status */
    if (sig_caught) {
        signal(sig_caught, SIG_DFL);
        raise(sig_caught);
    }
    /* I think we never end up here */
    return 0;
}