]> mj.ucw.cz Git - libucw.git/commitdiff
Daemon: Split to daemonization and control parts
authorMartin Mares <mj@ucw.cz>
Wed, 18 Jul 2012 08:39:09 +0000 (10:39 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 18 Jul 2012 08:39:09 +0000 (10:39 +0200)
ucw/Makefile
ucw/daemon-ctrl.c [new file with mode: 0644]
ucw/daemon.c

index 1d6db190fd8aa66fee5b5b13e52351b97587b7d9..f6cab5f148e0bfb5299df59da1f39cc4ce51f537 100644 (file)
@@ -34,7 +34,7 @@ LIBUCW_MODS= \
        getopt \
        strtonum \
        resource trans res-fd res-mem res-subpool res-mempool res-eltpool \
-       daemon
+       daemon daemon-ctrl
 
 LIBUCW_MAIN_INCLUDES= \
        lib.h log.h threads.h time.h \
diff --git a/ucw/daemon-ctrl.c b/ucw/daemon-ctrl.c
new file mode 100644 (file)
index 0000000..8d9bf72
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *     UCW Library -- Daemon Control
+ *
+ *     (c) 2012 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/daemon.h>
+#include <ucw/process.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+
+static enum daemon_control_status
+daemon_control_err(struct daemon_control_params *dc, char *msg, ...)
+{
+  va_list args;
+  va_start(args, msg);
+  vsnprintf(dc->error_msg, DAEMON_ERR_LEN, msg, args);
+  va_end(args);
+  return DAEMON_STATUS_ERROR;
+}
+
+static int
+daemon_read_pid(struct daemon_control_params *dc, int will_wait)
+{
+  int pid_fd = open(dc->pid_file, O_RDONLY);
+  if (pid_fd < 0)
+    {
+      if (errno == ENOENT)
+       return 0;
+      daemon_control_err(dc, "Cannot open PID file `%s': %m", dc->pid_file);
+      return -1;
+    }
+
+  if (flock(pid_fd, LOCK_EX | (will_wait ? 0 : LOCK_NB)) >= 0)
+    {
+      // The lock file is stale
+      close(pid_fd);
+      return 0;
+    }
+
+  if (errno != EINTR && errno != EWOULDBLOCK)
+    {
+      daemon_control_err(dc, "Cannot lock PID file `%s': %m", dc->pid_file);
+      goto fail;
+    }
+
+  char buf[16];
+  int n = read(pid_fd, buf, sizeof(buf));
+  if (n < 0)
+    {
+      daemon_control_err(dc, "Error reading `%s': %m", dc->pid_file);
+      goto fail;
+    }
+  if (n == (int) sizeof(buf))
+    {
+      daemon_control_err(dc, "PID file `%s' is too long", dc->pid_file);
+      goto fail;
+    }
+  buf[n] = 0;
+  int pid = atoi(buf);
+  if (!pid)
+    {
+      daemon_control_err(dc, "PID file `%s' does not contain a valid PID", dc->pid_file);
+      goto fail;
+    }
+  close(pid_fd);
+  return pid;
+
+fail:
+  close(pid_fd);
+  return -1;
+}
+
+enum daemon_control_status
+daemon_control(struct daemon_control_params *dc)
+{
+  enum daemon_control_status st = DAEMON_STATUS_ERROR;
+
+  int guard_fd = open(dc->guard_file, O_RDWR | O_CREAT, 0666);
+  if (guard_fd < 0)
+    return daemon_control_err(dc, "Cannot open guard file `%s': %m", dc->guard_file);
+  if (flock(guard_fd, LOCK_EX) < 0)
+    return daemon_control_err(dc, "Cannot lock guard file `%s': %m", dc->guard_file);
+
+  // Read the PID file
+  int pid = daemon_read_pid(dc, 0);
+  if (pid < 0)
+    goto done;
+
+  switch (dc->action)
+    {
+    case DAEMON_CONTROL_CHECK:
+      if (pid)
+       st = DAEMON_STATUS_OK;
+      else
+       st = DAEMON_STATUS_NOT_RUNNING;
+      break;
+    case DAEMON_CONTROL_START:
+      if (pid)
+       st = DAEMON_STATUS_ALREADY_DONE;
+      else
+       {
+         pid_t pp = fork();
+         if (pp < 0)
+           {
+             daemon_control_err(dc, "Cannot fork: %m");
+             goto done;
+           }
+         if (pp)
+           {
+             close(guard_fd);
+             execvp(dc->argv[0], dc->argv);
+             fprintf(stderr, "Cannot execute `%s': %m\n", dc->argv[0]);
+             exit(DAEMON_STATUS_ERROR);
+           }
+         int stat;
+         int ec = waitpid(pp, &stat, 0);
+         if (ec < 0)
+           {
+             daemon_control_err(dc, "Cannot wait: %m");
+             goto done;
+           }
+         if (WIFEXITED(stat) && WEXITSTATUS(stat) == DAEMON_STATUS_ERROR)
+           {
+             daemon_control_err(dc, "Cannot execute the daemon");
+             goto done;
+           }
+         char ecmsg[EXIT_STATUS_MSG_SIZE];
+         if (format_exit_status(ecmsg, stat))
+           {
+             daemon_control_err(dc, "Daemon %s", ecmsg);
+             goto done;
+           }
+         pid = daemon_read_pid(dc, 0);
+         if (!pid)
+           daemon_control_err(dc, "Daemon failed to write the PID file `%s'", dc->pid_file);
+         else
+           st = DAEMON_STATUS_OK;
+       }
+      break;
+    case DAEMON_CONTROL_STOP:
+      if (!pid)
+       return DAEMON_STATUS_ALREADY_DONE;
+      int sig = dc->signal ? : SIGTERM;
+      if (kill(pid, sig) < 0)
+       {
+         daemon_control_err(dc, "Cannot send signal %d: %m", dc->signal);
+         goto done;
+       }
+      pid = daemon_read_pid(dc, 1);
+      ASSERT(pid <= 0);
+      if (!pid)
+       st = DAEMON_STATUS_OK;
+      break;
+    case DAEMON_CONTROL_SIGNAL:
+      if (!pid)
+       return DAEMON_STATUS_NOT_RUNNING;
+      if (kill(pid, dc->signal) < 0)
+       daemon_control_err(dc, "Cannot send signal %d: %m", dc->signal);
+      else
+       st = DAEMON_STATUS_OK;
+      break;
+    default:
+      ASSERT(0);
+    }
+
+done:
+  close(guard_fd);
+  return st;
+}
index 9f3273df73b6d438e4116d75f0c90464b99d9aa6..7606f8075d7322e55f4b6e21c80d0c8cddeee997 100644 (file)
 #include <ucw/lib.h>
 #include <ucw/daemon.h>
 #include <ucw/strtonum.h>
-#include <ucw/process.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <pwd.h>
 #include <grp.h>
 #include <errno.h>
-#include <signal.h>
 #include <sys/file.h>
-#include <sys/wait.h>
 
 static void
 daemon_resolve_ugid(struct daemon_params *dp)
@@ -180,166 +176,6 @@ daemon_exit(struct daemon_params *dp)
     }
 }
 
-static enum daemon_control_status
-daemon_control_err(struct daemon_control_params *dc, char *msg, ...)
-{
-  va_list args;
-  va_start(args, msg);
-  vsnprintf(dc->error_msg, DAEMON_ERR_LEN, msg, args);
-  va_end(args);
-  return DAEMON_STATUS_ERROR;
-}
-
-static int
-daemon_read_pid(struct daemon_control_params *dc, int will_wait)
-{
-  int pid_fd = open(dc->pid_file, O_RDONLY);
-  if (pid_fd < 0)
-    {
-      if (errno == ENOENT)
-       return 0;
-      daemon_control_err(dc, "Cannot open PID file `%s': %m", dc->pid_file);
-      return -1;
-    }
-
-  if (flock(pid_fd, LOCK_EX | (will_wait ? 0 : LOCK_NB)) >= 0)
-    {
-      // The lock file is stale
-      close(pid_fd);
-      return 0;
-    }
-
-  if (errno != EINTR && errno != EWOULDBLOCK)
-    {
-      daemon_control_err(dc, "Cannot lock PID file `%s': %m", dc->pid_file);
-      goto fail;
-    }
-
-  char buf[16];
-  int n = read(pid_fd, buf, sizeof(buf));
-  if (n < 0)
-    {
-      daemon_control_err(dc, "Error reading `%s': %m", dc->pid_file);
-      goto fail;
-    }
-  if (n == (int) sizeof(buf))
-    {
-      daemon_control_err(dc, "PID file `%s' is too long", dc->pid_file);
-      goto fail;
-    }
-  buf[n] = 0;
-  int pid = atoi(buf);
-  if (!pid)
-    {
-      daemon_control_err(dc, "PID file `%s' does not contain a valid PID", dc->pid_file);
-      goto fail;
-    }
-  close(pid_fd);
-  return pid;
-
-fail:
-  close(pid_fd);
-  return -1;
-}
-
-enum daemon_control_status
-daemon_control(struct daemon_control_params *dc)
-{
-  enum daemon_control_status st = DAEMON_STATUS_ERROR;
-
-  int guard_fd = open(dc->guard_file, O_RDWR | O_CREAT, 0666);
-  if (guard_fd < 0)
-    return daemon_control_err(dc, "Cannot open guard file `%s': %m", dc->guard_file);
-  if (flock(guard_fd, LOCK_EX) < 0)
-    return daemon_control_err(dc, "Cannot lock guard file `%s': %m", dc->guard_file);
-
-  // Read the PID file
-  int pid = daemon_read_pid(dc, 0);
-  if (pid < 0)
-    goto done;
-
-  switch (dc->action)
-    {
-    case DAEMON_CONTROL_CHECK:
-      if (pid)
-       st = DAEMON_STATUS_OK;
-      else
-       st = DAEMON_STATUS_NOT_RUNNING;
-      break;
-    case DAEMON_CONTROL_START:
-      if (pid)
-       st = DAEMON_STATUS_ALREADY_DONE;
-      else
-       {
-         pid_t pp = fork();
-         if (pp < 0)
-           {
-             daemon_control_err(dc, "Cannot fork: %m");
-             goto done;
-           }
-         if (pp)
-           {
-             close(guard_fd);
-             execvp(dc->argv[0], dc->argv);
-             fprintf(stderr, "Cannot execute `%s': %m\n", dc->argv[0]);
-             exit(DAEMON_STATUS_ERROR);
-           }
-         int stat;
-         int ec = waitpid(pp, &stat, 0);
-         if (ec < 0)
-           {
-             daemon_control_err(dc, "Cannot wait: %m");
-             goto done;
-           }
-         if (WIFEXITED(stat) && WEXITSTATUS(stat) == DAEMON_STATUS_ERROR)
-           {
-             daemon_control_err(dc, "Cannot execute the daemon");
-             goto done;
-           }
-         char ecmsg[EXIT_STATUS_MSG_SIZE];
-         if (format_exit_status(ecmsg, stat))
-           {
-             daemon_control_err(dc, "Daemon %s", ecmsg);
-             goto done;
-           }
-         pid = daemon_read_pid(dc, 0);
-         if (!pid)
-           daemon_control_err(dc, "Daemon failed to write the PID file `%s'", dc->pid_file);
-         else
-           st = DAEMON_STATUS_OK;
-       }
-      break;
-    case DAEMON_CONTROL_STOP:
-      if (!pid)
-       return DAEMON_STATUS_ALREADY_DONE;
-      int sig = dc->signal ? : SIGTERM;
-      if (kill(pid, sig) < 0)
-       {
-         daemon_control_err(dc, "Cannot send signal %d: %m", dc->signal);
-         goto done;
-       }
-      pid = daemon_read_pid(dc, 1);
-      ASSERT(pid <= 0);
-      if (!pid)
-       st = DAEMON_STATUS_OK;
-      break;
-    case DAEMON_CONTROL_SIGNAL:
-      if (!pid)
-       return DAEMON_STATUS_NOT_RUNNING;
-      if (kill(pid, dc->signal) < 0)
-       daemon_control_err(dc, "Cannot send signal %d: %m", dc->signal);
-      else
-       st = DAEMON_STATUS_OK;
-      break;
-    default:
-      ASSERT(0);
-    }
-
-done:
-  close(guard_fd);
-  return st;
-}
-
 #ifdef TEST
 
 static void body(struct daemon_params *dp)