From: Stewart Smith Date: Fri, 11 Feb 2011 01:06:24 +0000 (+1100) Subject: move daemon-with-notify to daemon_with_notify as dashes aren't allowed in CCAN module... X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=aaf830998ef2dc127dd09f30fc9a2156e0634a57 move daemon-with-notify to daemon_with_notify as dashes aren't allowed in CCAN module names (and ccanlint segfaults on them) --- diff --git a/ccan/daemon-with-notify/LICENSE b/ccan/daemon-with-notify/LICENSE deleted file mode 120000 index f8598ee1..00000000 --- a/ccan/daemon-with-notify/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../licenses/BSD \ No newline at end of file diff --git a/ccan/daemon-with-notify/_info b/ccan/daemon-with-notify/_info deleted file mode 100644 index 701ca613..00000000 --- a/ccan/daemon-with-notify/_info +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include "config.h" - -/** - * daemon-with-notify - turn a process into a daemon with parent exiting when - * child has decided that it has started correctly. - * - * Daemons should detach themselves thoroughly from the process which launched - * them, and not prevent any filesystems from being unmounted. daemonize() - * helps with the process. - * - * Daemon-with-notify is different in that the child can send a SIGUSR1 to - * the parent to indicate it has started (e.g. after memory allocation and - * other things that may fail) so that the parent can return a success or - * failing exit code and init scripts can pick this up easily. - * - * Example: - * #include - * #include - * #include - * #include - * #include - * - * static void usage(const char *name) - * { - * errx(1, "Usage: %s [--daemonize]\n", name); - * } - * - * // Wait for a minute, possibly as a daemon. - * int main(int argc, char *argv[]) - * { - * if (argc != 1) { - * if (argc == 2 && streq(argv[1], "--daemonize")) { - * if (!daemonize(1, 1, 1)) - * err(1, "Failed to become daemon"); - * } else - * usage(argv[1]); - * } - * sleep(10); // do some init here - * daemon_is_ready(); - * sleep(20); // will be done in child, detached from parent - * exit(0); - * } - * - * License: BSD-MIT - */ -int main(int argc, char *argv[]) -{ - if (argc != 2) - return 1; - - if (strcmp(argv[1], "depends") == 0) { - return 0; - } - - if (strcmp(argv[1], "libs") == 0) { - return 0; - } - - return 1; -} diff --git a/ccan/daemon-with-notify/daemon-with-notify.c b/ccan/daemon-with-notify/daemon-with-notify.c deleted file mode 100644 index 03c6d380..00000000 --- a/ccan/daemon-with-notify/daemon-with-notify.c +++ /dev/null @@ -1,131 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 2010 - * Stewart Smith - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -void sigusr1_handler(int sig); - -pid_t parent_pid; - -void sigusr1_handler(int sig) -{ - if (sig == SIGUSR1) - _exit(EXIT_SUCCESS); -} - -int daemon_is_ready(void) -{ - kill(parent_pid, SIGUSR1); - return 0; -} - -int daemonize(int nochdir, int noclose, int wait_sigusr1) -{ - int fd; - pid_t child= -1; - - parent_pid= getpid(); - signal(SIGUSR1, sigusr1_handler); - - child= fork(); - - switch (child) - { - case -1: - return (-1); - case 0: - break; - default: - if (wait_sigusr1) - { - /* parent */ - int exit_code= -1; - int status; - while (waitpid(child, &status, 0) != child); - if (WIFEXITED(status)) - { - exit_code= WEXITSTATUS(status); - } - if (WIFSIGNALED(status)) - { - exit_code= -1; - } - _exit(exit_code); - } - else - { - _exit(EXIT_SUCCESS); - } - } - - /* child */ - if (setsid() == -1) - return (-1); - - if (nochdir == 0) { - if(chdir("/") != 0) { - perror("chdir"); - return (-1); - } - } - - if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) { - if(dup2(fd, STDIN_FILENO) < 0) { - perror("dup2 stdin"); - return (-1); - } - if(dup2(fd, STDOUT_FILENO) < 0) { - perror("dup2 stdout"); - return (-1); - } - if(dup2(fd, STDERR_FILENO) < 0) { - perror("dup2 stderr"); - return (-1); - } - - if (fd > STDERR_FILENO) { - if(close(fd) < 0) { - perror("close"); - return (-1); - } - } - } - return (0); -} diff --git a/ccan/daemon-with-notify/daemon-with-notify.h b/ccan/daemon-with-notify/daemon-with-notify.h deleted file mode 100644 index f80e7f51..00000000 --- a/ccan/daemon-with-notify/daemon-with-notify.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CCAN_DAEMON_WITH_NOTIFY_H -#define CCAN_DAEMON_WITH_NOTIFY_H - -/** - * daemonize - turns this process into a daemon - * - * This routine will fork() us off to become a daemon. It will return - * -1 on error and 0 on success. - * - * It has a few optional behaviours: - * @nochdir: if nochdir is set, it won't chdir to / - * this means we could hold onto mounts - * @noclose: if noclose is set, we won't close stdout, stdin and stderr. - * @wait_sigusr1: if wait_sigusr1 is set, the parent will not exit until the - * child has either exited OR it receives a SIGUSR1 signal. You can use this - * to have the parent only exit when your process has done all the - * danegerous initialization that could cause it to fail to start - * (e.g. allocating large amounts of memory, replaying REDO logs). - * This allows init scripts starting the daemon to easily report - * success/failure. - */ -int daemonize(int nochdir, int noclose, int wait_sigusr1); - -/** - * daemon_is_ready - signals parent that it can exit, we started okay - * - * After a daemonize() call, this function will send a SIGUSR1 to the parent - * telling it to exit as we have started up okay. - */ -int daemon_is_ready(void); - -#endif /* CCAN_DAEMON_WITH_NOTIFY_H */ diff --git a/ccan/daemon-with-notify/test/run.c b/ccan/daemon-with-notify/test/run.c deleted file mode 100644 index 70ccfbbe..00000000 --- a/ccan/daemon-with-notify/test/run.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -struct child_data { - pid_t pid; - pid_t ppid; - int in_root_dir; - int read_from_stdin, write_to_stdout, write_to_stderr; -}; - -int main(int argc, char *argv[]) -{ - int fds[2]; - struct child_data daemonized; - pid_t pid; - - plan_tests(6); - - if (pipe(fds) != 0) - err(1, "Failed pipe"); - - /* Since daemonize forks and parent exits, we need to fork - * that parent. */ - pid = fork(); - if (pid == -1) - err(1, "Failed fork"); - - if (pid == 0) { - char buffer[2]; - pid = getpid(); - daemonize(0, 0, 1); - daemon_is_ready(); - /* Keep valgrind happy about uninitialized bytes. */ - memset(&daemonized, 0, sizeof(daemonized)); - daemonized.pid = getpid(); - daemonized.in_root_dir = (getcwd(buffer, 2) != NULL); - daemonized.read_from_stdin - = read(STDIN_FILENO, buffer, 1) == -1 ? errno : 0; - daemonized.write_to_stdout - = write(STDOUT_FILENO, buffer, 1) == -1 ? errno : 0; - if (write(STDERR_FILENO, buffer, 1) != 1) { - daemonized.write_to_stderr = errno; - if (daemonized.write_to_stderr == 0) - daemonized.write_to_stderr = -1; - } else - daemonized.write_to_stderr = 0; - - /* Make sure parent exits. */ - while (getppid() == pid) - sleep(1); - daemonized.ppid = getppid(); - if (write(fds[1], &daemonized, sizeof(daemonized)) - != sizeof(daemonized)) - exit(1); - exit(0); - } - - if (read(fds[0], &daemonized, sizeof(daemonized)) != sizeof(daemonized)) - err(1, "Failed read"); - - ok1(daemonized.pid != pid); - ok1(daemonized.ppid == 1); - ok1(daemonized.in_root_dir); - ok1(daemonized.read_from_stdin == 0); - ok1(daemonized.write_to_stdout == 0); - ok1(daemonized.write_to_stderr == 0); - - return exit_status(); -} diff --git a/ccan/daemon_with_notify/LICENSE b/ccan/daemon_with_notify/LICENSE new file mode 120000 index 00000000..f8598ee1 --- /dev/null +++ b/ccan/daemon_with_notify/LICENSE @@ -0,0 +1 @@ +../../licenses/BSD \ No newline at end of file diff --git a/ccan/daemon_with_notify/_info b/ccan/daemon_with_notify/_info new file mode 100644 index 00000000..6f26898e --- /dev/null +++ b/ccan/daemon_with_notify/_info @@ -0,0 +1,63 @@ +#include +#include +#include "config.h" + +/** + * daemon_with_notify - daemonize a process, can wait for child to signal readiness + * + * Daemons should detach themselves thoroughly from the process which launched + * them, and not prevent any filesystems from being unmounted. daemonize() + * helps with the process. + * + * Daemon-with-notify is different in that the child can send a SIGUSR1 to + * the parent to indicate it has started (e.g. after memory allocation and + * other things that may fail) so that the parent can return a success or + * failing exit code and init scripts can pick this up easily. + * + * Example: + * #include + * #include + * #include + * #include + * #include + * + * static void usage(const char *name) + * { + * errx(1, "Usage: %s [--daemonize]\n", name); + * } + * + * // Wait for a minute, possibly as a daemon. + * int main(int argc, char *argv[]) + * { + * if (argc != 1) { + * if (argc == 2 && streq(argv[1], "--daemonize")) { + * if (!daemonize(1, 1, 1)) + * err(1, "Failed to become daemon"); + * } else + * usage(argv[1]); + * } + * sleep(10); // do some init here + * daemon_is_ready(); + * sleep(20); // will be done in child, detached from parent + * exit(0); + * } + * + * License: BSD + * Author: Stewart Smith + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + return 0; + } + + if (strcmp(argv[1], "libs") == 0) { + return 0; + } + + return 1; +} + diff --git a/ccan/daemon_with_notify/daemon_with_notify.c b/ccan/daemon_with_notify/daemon_with_notify.c new file mode 100644 index 00000000..bcc627bb --- /dev/null +++ b/ccan/daemon_with_notify/daemon_with_notify.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2010 + * Stewart Smith + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +void sigusr1_handler(int sig); + +pid_t parent_pid; + +void sigusr1_handler(int sig) +{ + if (sig == SIGUSR1) + _exit(EXIT_SUCCESS); +} + +int daemon_is_ready(void) +{ + kill(parent_pid, SIGUSR1); + return 0; +} + +int daemonize(int nochdir, int noclose, int wait_sigusr1) +{ + int fd; + pid_t child= -1; + + parent_pid= getpid(); + signal(SIGUSR1, sigusr1_handler); + + child= fork(); + + switch (child) + { + case -1: + return (-1); + case 0: + break; + default: + if (wait_sigusr1) + { + /* parent */ + int exit_code= -1; + int status; + while (waitpid(child, &status, 0) != child); + if (WIFEXITED(status)) + { + exit_code= WEXITSTATUS(status); + } + if (WIFSIGNALED(status)) + { + exit_code= -1; + } + _exit(exit_code); + } + else + { + _exit(EXIT_SUCCESS); + } + } + + /* child */ + if (setsid() == -1) + return (-1); + + if (nochdir == 0) { + if(chdir("/") != 0) { + perror("chdir"); + return (-1); + } + } + + if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) { + if(dup2(fd, STDIN_FILENO) < 0) { + perror("dup2 stdin"); + return (-1); + } + if(dup2(fd, STDOUT_FILENO) < 0) { + perror("dup2 stdout"); + return (-1); + } + if(dup2(fd, STDERR_FILENO) < 0) { + perror("dup2 stderr"); + return (-1); + } + + if (fd > STDERR_FILENO) { + if(close(fd) < 0) { + perror("close"); + return (-1); + } + } + } + return (0); +} diff --git a/ccan/daemon_with_notify/daemon_with_notify.h b/ccan/daemon_with_notify/daemon_with_notify.h new file mode 100644 index 00000000..f80e7f51 --- /dev/null +++ b/ccan/daemon_with_notify/daemon_with_notify.h @@ -0,0 +1,32 @@ +#ifndef CCAN_DAEMON_WITH_NOTIFY_H +#define CCAN_DAEMON_WITH_NOTIFY_H + +/** + * daemonize - turns this process into a daemon + * + * This routine will fork() us off to become a daemon. It will return + * -1 on error and 0 on success. + * + * It has a few optional behaviours: + * @nochdir: if nochdir is set, it won't chdir to / + * this means we could hold onto mounts + * @noclose: if noclose is set, we won't close stdout, stdin and stderr. + * @wait_sigusr1: if wait_sigusr1 is set, the parent will not exit until the + * child has either exited OR it receives a SIGUSR1 signal. You can use this + * to have the parent only exit when your process has done all the + * danegerous initialization that could cause it to fail to start + * (e.g. allocating large amounts of memory, replaying REDO logs). + * This allows init scripts starting the daemon to easily report + * success/failure. + */ +int daemonize(int nochdir, int noclose, int wait_sigusr1); + +/** + * daemon_is_ready - signals parent that it can exit, we started okay + * + * After a daemonize() call, this function will send a SIGUSR1 to the parent + * telling it to exit as we have started up okay. + */ +int daemon_is_ready(void); + +#endif /* CCAN_DAEMON_WITH_NOTIFY_H */ diff --git a/ccan/daemon_with_notify/test/run.c b/ccan/daemon_with_notify/test/run.c new file mode 100644 index 00000000..3af42043 --- /dev/null +++ b/ccan/daemon_with_notify/test/run.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct child_data { + pid_t pid; + pid_t ppid; + int in_root_dir; + int read_from_stdin, write_to_stdout, write_to_stderr; +}; + +int main(int argc, char *argv[]) +{ + int fds[2]; + struct child_data daemonized; + pid_t pid; + + plan_tests(6); + + if (pipe(fds) != 0) + err(1, "Failed pipe"); + + /* Since daemonize forks and parent exits, we need to fork + * that parent. */ + pid = fork(); + if (pid == -1) + err(1, "Failed fork"); + + if (pid == 0) { + char buffer[2]; + pid = getpid(); + daemonize(0, 0, 1); + daemon_is_ready(); + /* Keep valgrind happy about uninitialized bytes. */ + memset(&daemonized, 0, sizeof(daemonized)); + daemonized.pid = getpid(); + daemonized.in_root_dir = (getcwd(buffer, 2) != NULL); + daemonized.read_from_stdin + = read(STDIN_FILENO, buffer, 1) == -1 ? errno : 0; + daemonized.write_to_stdout + = write(STDOUT_FILENO, buffer, 1) == -1 ? errno : 0; + if (write(STDERR_FILENO, buffer, 1) != 1) { + daemonized.write_to_stderr = errno; + if (daemonized.write_to_stderr == 0) + daemonized.write_to_stderr = -1; + } else + daemonized.write_to_stderr = 0; + + /* Make sure parent exits. */ + while (getppid() == pid) + sleep(1); + daemonized.ppid = getppid(); + if (write(fds[1], &daemonized, sizeof(daemonized)) + != sizeof(daemonized)) + exit(1); + exit(0); + } + + if (read(fds[0], &daemonized, sizeof(daemonized)) != sizeof(daemonized)) + err(1, "Failed read"); + + ok1(daemonized.pid != pid); + ok1(daemonized.ppid == 1); + ok1(daemonized.in_root_dir); + ok1(daemonized.read_from_stdin == 0); + ok1(daemonized.write_to_stdout == 0); + ok1(daemonized.write_to_stderr == 0); + + return exit_status(); +}