~jan-kneschke/mysql-proxy/packet-tracking-assertions

« back to all changes in this revision

Viewing changes to src/chassis-unix-daemon.c

  • Committer: Kay Roepke
  • Date: 2009-06-03 12:51:29 UTC
  • mto: This revision was merged to the branch mainline in revision 639.
  • Revision ID: kay@sun.com-20090603125129-26oso9ov7yinwocg
add autoconf/aclocal files we should never commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $%BEGINLICENSE%$
2
 
 Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3
 
 
4
 
 This program is free software; you can redistribute it and/or
5
 
 modify it under the terms of the GNU General Public License as
6
 
 published by the Free Software Foundation; version 2 of the
7
 
 License.
8
 
 
9
 
 This program is distributed in the hope that it will be useful,
10
 
 but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 
 GNU General Public License for more details.
13
 
 
14
 
 You should have received a copy of the GNU General Public License
15
 
 along with this program; if not, write to the Free Software
16
 
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17
 
 02110-1301  USA
18
 
 
19
 
 $%ENDLICENSE%$ */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "config.h"
23
 
#endif
24
 
 
25
 
#ifdef HAVE_SYS_WAIT_H
26
 
#include <sys/wait.h> /* wait4 */
27
 
#endif
28
 
#include <sys/stat.h>
29
 
#ifdef HAVE_SYS_RESOURCE_H
30
 
#include <sys/resource.h> /* getrusage */
31
 
#endif
32
 
 
33
 
#include <stdlib.h>
34
 
#include <string.h>
35
 
#ifdef HAVE_UNISTD_H
36
 
#include <unistd.h>
37
 
#endif
38
 
#include <errno.h>
39
 
#include <signal.h>
40
 
 
41
 
#include <glib.h>
42
 
 
43
 
#include "chassis-unix-daemon.h"
44
 
 
45
 
/**
46
 
 * start the app in the background 
47
 
 * 
48
 
 * UNIX-version
49
 
 */
50
 
void chassis_unix_daemonize(void) {
51
 
#ifdef _WIN32
52
 
        g_assert_not_reached(); /* shouldn't be tried to be called on win32 */
53
 
#else
54
 
#ifdef SIGTTOU
55
 
        signal(SIGTTOU, SIG_IGN);
56
 
#endif
57
 
#ifdef SIGTTIN
58
 
        signal(SIGTTIN, SIG_IGN);
59
 
#endif
60
 
#ifdef SIGTSTP
61
 
        signal(SIGTSTP, SIG_IGN);
62
 
#endif
63
 
        if (fork() != 0) exit(0);
64
 
        
65
 
        if (setsid() == -1) exit(0);
66
 
 
67
 
        signal(SIGHUP, SIG_IGN);
68
 
 
69
 
        if (fork() != 0) exit(0);
70
 
        
71
 
        chdir("/");
72
 
        
73
 
        umask(0);
74
 
#endif
75
 
}
76
 
 
77
 
 
78
 
/**
79
 
 * forward the signal to the process group, but not us
80
 
 */
81
 
static void chassis_unix_signal_forward(int sig) {
82
 
#ifdef _WIN32
83
 
        g_assert_not_reached(); /* shouldn't be tried to be called on win32 */
84
 
#else
85
 
        signal(sig, SIG_IGN); /* we don't want to create a loop here */
86
 
 
87
 
        kill(0, sig);
88
 
#endif
89
 
}
90
 
 
91
 
/**
92
 
 * keep the ourself alive 
93
 
 *
94
 
 * if we or the child gets a SIGTERM, we quit too
95
 
 * on everything else we restart it
96
 
 */
97
 
int chassis_unix_proc_keepalive(int *child_exit_status) {
98
 
#ifdef _WIN32
99
 
        g_assert_not_reached(); /* shouldn't be tried to be called on win32 */
100
 
        return 0; /* for VC++, to silence a warning */
101
 
#else
102
 
        int nprocs = 0;
103
 
        pid_t child_pid = -1;
104
 
 
105
 
        /* we ignore SIGINT and SIGTERM and just let it be forwarded to the child instead
106
 
         * as we want to collect its PID before we shutdown too 
107
 
         *
108
 
         * the child will have to set its own signal handlers for this
109
 
         */
110
 
 
111
 
        for (;;) {
112
 
                /* try to start the children */
113
 
                while (nprocs < 1) {
114
 
                        pid_t pid = fork();
115
 
 
116
 
                        if (pid == 0) {
117
 
                                /* child */
118
 
                                
119
 
                                g_debug("%s: we are the child: %d",
120
 
                                                G_STRLOC,
121
 
                                                getpid());
122
 
                                return 0;
123
 
                        } else if (pid < 0) {
124
 
                                /* fork() failed */
125
 
 
126
 
                                g_critical("%s: fork() failed: %s (%d)",
127
 
                                        G_STRLOC,
128
 
                                        g_strerror(errno),
129
 
                                        errno);
130
 
 
131
 
                                return -1;
132
 
                        } else {
133
 
                                /* we are the angel, let's see what the child did */
134
 
                                g_message("%s: [angel] we try to keep PID=%d alive",
135
 
                                                G_STRLOC,
136
 
                                                pid);
137
 
 
138
 
                                /* forward a few signals that are sent to us to the child instead */
139
 
                                signal(SIGINT, chassis_unix_signal_forward);
140
 
                                signal(SIGTERM, chassis_unix_signal_forward);
141
 
                                signal(SIGHUP, chassis_unix_signal_forward);
142
 
                                signal(SIGUSR1, chassis_unix_signal_forward);
143
 
                                signal(SIGUSR2, chassis_unix_signal_forward);
144
 
 
145
 
                                child_pid = pid;
146
 
                                nprocs++;
147
 
                        }
148
 
                }
149
 
 
150
 
                if (child_pid != -1) {
151
 
                        struct rusage rusage;
152
 
                        int exit_status;
153
 
                        pid_t exit_pid;
154
 
 
155
 
                        g_debug("%s: waiting for %d",
156
 
                                        G_STRLOC,
157
 
                                        child_pid);
158
 
#ifdef HAVE_WAIT4
159
 
                        exit_pid = wait4(child_pid, &exit_status, 0, &rusage);
160
 
#else
161
 
                        memset(&rusage, 0, sizeof(rusage)); /* make sure everything is zero'ed out */
162
 
                        exit_pid = waitpid(child_pid, &exit_status, 0);
163
 
#endif
164
 
                        g_debug("%s: %d returned: %d",
165
 
                                        G_STRLOC,
166
 
                                        child_pid,
167
 
                                        exit_pid);
168
 
 
169
 
                        if (exit_pid == child_pid) {
170
 
                                /* our child returned, let's see how it went */
171
 
                                if (WIFEXITED(exit_status)) {
172
 
                                        g_message("%s: [angel] PID=%d exited normally with exit-code = %d (it used %ld kBytes max)",
173
 
                                                        G_STRLOC,
174
 
                                                        child_pid,
175
 
                                                        WEXITSTATUS(exit_status),
176
 
                                                        rusage.ru_maxrss / 1024);
177
 
                                        if (child_exit_status) *child_exit_status = WEXITSTATUS(exit_status);
178
 
                                        return 1;
179
 
                                } else if (WIFSIGNALED(exit_status)) {
180
 
                                        int time_towait = 2;
181
 
                                        /* our child died on a signal
182
 
                                         *
183
 
                                         * log it and restart */
184
 
 
185
 
                                        g_critical("%s: [angel] PID=%d died on signal=%d (it used %ld kBytes max) ... waiting 3min before restart",
186
 
                                                        G_STRLOC,
187
 
                                                        child_pid,
188
 
                                                        WTERMSIG(exit_status),
189
 
                                                        rusage.ru_maxrss / 1024);
190
 
 
191
 
                                        /**
192
 
                                         * to make sure we don't loop as fast as we can, sleep a bit between 
193
 
                                         * restarts
194
 
                                         */
195
 
        
196
 
                                        signal(SIGINT, SIG_DFL);
197
 
                                        signal(SIGTERM, SIG_DFL);
198
 
                                        signal(SIGHUP, SIG_DFL);
199
 
                                        while (time_towait > 0) time_towait = sleep(time_towait);
200
 
 
201
 
                                        nprocs--;
202
 
                                        child_pid = -1;
203
 
                                } else if (WIFSTOPPED(exit_status)) {
204
 
                                } else {
205
 
                                        g_assert_not_reached();
206
 
                                }
207
 
                        } else if (-1 == exit_pid) {
208
 
                                /* EINTR is ok, all others bad */
209
 
                                if (EINTR != errno) {
210
 
                                        /* how can this happen ? */
211
 
                                        g_critical("%s: wait4(%d, ...) failed: %s (%d)",
212
 
                                                G_STRLOC,
213
 
                                                child_pid,
214
 
                                                g_strerror(errno),
215
 
                                                errno);
216
 
 
217
 
                                        return -1;
218
 
                                }
219
 
                        } else {
220
 
                                g_assert_not_reached();
221
 
                        }
222
 
                }
223
 
        }
224
 
#endif
225
 
}
226