2 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions
6 * of the GNU General Public License v.2.
8 * You should have received a copy of the GNU General Public License
9 * along with this program; if not, write to the Free Software Foundation,
10 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #include "functions.h"
20 #include <sys/socket.h>
25 static volatile sig_atomic_t exit_now = 0;
26 /* FIXME Review signal handling. Should be volatile sig_atomic_t */
27 static sigset_t signal_mask;
28 static volatile sig_atomic_t signal_received;
30 static void process_signals(void);
31 static void daemonize(void);
32 static void init_all(void);
33 static void cleanup_all(void);
35 int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
41 /* Parent can now exit, we're ready to handle requests */
42 kill(getppid(), SIGTERM);
44 LOG_PRINT("Starting cmirrord:");
45 LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
46 LOG_DBG(" Compiled with debugging.");
51 links_issue_callbacks();
59 * parent_exit_handler: exit the parent
63 static void parent_exit_handler(int sig __attribute__((unused)))
68 static void sig_handler(int sig)
70 /* FIXME Races - don't touch signal_mask here. */
71 sigaddset(&signal_mask, sig);
75 static void process_signal(int sig){
92 LOG_PRINT("Unknown signal received... ignoring");
97 LOG_DBG("No current cluster logs... safe to exit.");
102 LOG_ERROR("Cluster logs exist. Refusing to exit.");
105 static void process_signals(void)
109 if (!signal_received)
114 for (x = 1; x < _NSIG; x++) {
115 if (sigismember(&signal_mask, x)) {
116 sigdelset(&signal_mask, x);
122 static void remove_lockfile(void)
124 unlink(CMIRRORD_PIDFILE);
130 * Performs the steps necessary to become a daemon.
132 static void daemonize(void)
137 signal(SIGTERM, &parent_exit_handler);
142 LOG_ERROR("Unable to fork()");
147 /* Parent waits here for child to get going */
148 while (!waitpid(pid, &status, WNOHANG) && !exit_now);
152 switch (WEXITSTATUS(status)) {
154 LOG_ERROR("Failed to create lockfile");
155 LOG_ERROR("Process already running?");
157 case EXIT_KERNEL_SOCKET:
158 LOG_ERROR("Unable to create netlink socket");
160 case EXIT_KERNEL_BIND:
161 LOG_ERROR("Unable to bind to netlink socket");
163 case EXIT_KERNEL_SETSOCKOPT:
164 LOG_ERROR("Unable to setsockopt on netlink socket");
166 case EXIT_CLUSTER_CKPT_INIT:
167 LOG_ERROR("Unable to initialize checkpoint service");
168 LOG_ERROR("Has the cluster infrastructure been started?");
171 LOG_ERROR("Failed to start: Generic error");
174 LOG_ERROR("Failed to start: Unknown error");
184 close(0); close(1); close(2);
185 open("/dev/null", O_RDONLY); /* reopen stdin */
186 open("/dev/null", O_WRONLY); /* reopen stdout */
187 open("/dev/null", O_WRONLY); /* reopen stderr */
189 LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
191 (void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
192 if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
194 (void) dm_prepare_selinux_context(NULL, 0);
196 atexit(remove_lockfile);
198 /* FIXME Replace with sigaction. (deprecated) */
199 signal(SIGINT, &sig_handler);
200 signal(SIGQUIT, &sig_handler);
201 signal(SIGTERM, &sig_handler);
202 signal(SIGHUP, &sig_handler);
203 signal(SIGPIPE, SIG_IGN);
204 signal(SIGUSR1, &sig_handler);
205 signal(SIGUSR2, &sig_handler);
206 sigemptyset(&signal_mask);
213 * Initialize modules. Exit on failure.
215 static void init_all(void)
219 if ((r = init_local()) ||
220 (r = init_cluster())) {
228 * Clean up before exiting
230 static void cleanup_all(void)