4 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU General Public License v.2.
10 * You should have received a copy of the GNU General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #include "configure.h"
23 #include <sys/types.h>
29 #include <linux/types.h>
30 #include <sys/socket.h>
31 #include <linux/netlink.h>
32 #include <linux/dm-ioctl.h>
34 #include "dm-log-userspace.h"
35 #include "functions.h"
42 static int exit_now
= 0;
43 static sigset_t signal_mask
;
44 static int signal_received
;
46 static void process_signals(void);
47 static void daemonize(void);
48 static void init_all(void);
49 static void cleanup_all(void);
51 int main(int argc
, char *argv
[])
57 /* Parent can now exit, we're ready to handle requests */
58 kill(getppid(), SIGTERM
);
60 LOG_PRINT("Starting cmirrord:");
61 LOG_PRINT(" Built: "__DATE__
" "__TIME__
"\n");
62 LOG_DBG(" Compiled with debugging.");
67 links_issue_callbacks();
75 * parent_exit_handler: exit the parent
79 static void parent_exit_handler(int sig
)
85 * create_lockfile - create and lock a lock file
86 * @lockfile: location of lock file
88 * Returns: 0 on success, -1 otherwise
90 static int create_lockfile(char *lockfile
)
96 if((fd
= open(lockfile
, O_CREAT
| O_WRONLY
,
97 (S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
))) < 0)
100 lock
.l_type
= F_WRLCK
;
102 lock
.l_whence
= SEEK_SET
;
105 if (fcntl(fd
, F_SETLK
, &lock
) < 0) {
110 if (ftruncate(fd
, 0) < 0) {
115 sprintf(buffer
, "%d\n", getpid());
117 if(write(fd
, buffer
, strlen(buffer
)) < strlen(buffer
)){
126 static void sig_handler(int sig
)
128 sigaddset(&signal_mask
, sig
);
132 static void process_signal(int sig
){
149 LOG_PRINT("Unknown signal received... ignoring");
154 LOG_DBG("No current cluster logs... safe to exit.");
159 LOG_ERROR("Cluster logs exist. Refusing to exit.");
162 static void process_signals(void)
166 if (!signal_received
)
171 for (x
= 1; x
< _NSIG
; x
++) {
172 if (sigismember(&signal_mask
, x
)) {
173 sigdelset(&signal_mask
, x
);
182 * Performs the steps necessary to become a daemon.
184 static void daemonize(void)
189 signal(SIGTERM
, &parent_exit_handler
);
194 LOG_ERROR("Unable to fork()");
199 /* Parent waits here for child to get going */
200 while (!waitpid(pid
, &status
, WNOHANG
) && !exit_now
);
204 switch (WEXITSTATUS(status
)) {
206 LOG_ERROR("Failed to create lockfile");
207 LOG_ERROR("Process already running?");
209 case EXIT_KERNEL_SOCKET
:
210 LOG_ERROR("Unable to create netlink socket");
212 case EXIT_KERNEL_BIND
:
213 LOG_ERROR("Unable to bind to netlink socket");
215 case EXIT_KERNEL_SETSOCKOPT
:
216 LOG_ERROR("Unable to setsockopt on netlink socket");
218 case EXIT_CLUSTER_CKPT_INIT
:
219 LOG_ERROR("Unable to initialize checkpoint service");
220 LOG_ERROR("Has the cluster infrastructure been started?");
223 LOG_ERROR("Failed to start: Generic error");
226 LOG_ERROR("Failed to start: Unknown error");
236 close(0); close(1); close(2);
237 open("/dev/null", O_RDONLY
); /* reopen stdin */
238 open("/dev/null", O_WRONLY
); /* reopen stdout */
239 open("/dev/null", O_WRONLY
); /* reopen stderr */
241 LOG_OPEN("cmirrord", LOG_PID
, LOG_DAEMON
);
243 if (create_lockfile(CMIRRORD_PIDFILE
))
246 signal(SIGINT
, &sig_handler
);
247 signal(SIGQUIT
, &sig_handler
);
248 signal(SIGTERM
, &sig_handler
);
249 signal(SIGHUP
, &sig_handler
);
250 signal(SIGPIPE
, SIG_IGN
);
251 signal(SIGUSR1
, &sig_handler
);
252 signal(SIGUSR2
, &sig_handler
);
253 sigemptyset(&signal_mask
);
260 * Initialize modules. Exit on failure.
262 static void init_all(void)
266 if ((r
= init_local()) ||
267 (r
= init_cluster())) {
275 * Clean up before exiting
277 static void cleanup_all(void)