]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
privops: stop helper on exit
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 8 Dec 2015 10:10:52 +0000 (11:10 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 8 Dec 2015 16:50:09 +0000 (17:50 +0100)
With SOCK_DGRAM sockets, the helper doesn't stop as there is no error
received when the socket is closed on the daemon side.

Add a QUIT operation to the protocol which is requested when the daemon
is exiting. It has no response. Register the stopping function with
atexit() to stop the helper even when the daemon is not exiting cleanly,
e.g. due to a fatal error.

privops.c

index f5ad8f206073d4dc69c8546c7c0f3947073349b8..439b10aff837fe56d8a020f6060a52a2580a7988 100644 (file)
--- a/privops.c
+++ b/privops.c
@@ -36,6 +36,7 @@
 #define op_ADJTIME        1024
 #define op_SETTIMEOFDAY   1025
 #define op_BINDSOCKET     1026
+#define op_QUIT           1099
 
 union sockaddr_in46 {
   struct sockaddr_in in4;
@@ -234,8 +235,9 @@ helper_main(int fd)
 {
   PrvRequest req;
   PrvResponse res;
+  int quit = 0;
 
-  while (1) {
+  while (!quit) {
     if (!receive_from_daemon(fd, &req))
       /* read error or closed input - we cannot recover - give up */
       break;
@@ -256,6 +258,10 @@ helper_main(int fd)
         do_bindsocket(&req.u.bind_sock, &res);
         break;
 
+      case op_QUIT:
+        quit = 1;
+        continue;
+
       default:
         res_fatal(&res, "Unexpected operator %d", req.op);
         break;
@@ -338,8 +344,11 @@ send_request(PrvRequest *req)
     *ptr_send_fd = req->u.bind_sock.sock;
   }
 
-  if (sendmsg(helper_fd, &msg, 0) < 0)
+  if (sendmsg(helper_fd, &msg, 0) < 0) {
+    /* don't try to send another request from exit() */
+    helper_fd = -1;
     LOG_FATAL(LOGF_PrivOps, "Could not send to helper : %s", strerror(errno));
+  }
 
   DEBUG_LOG(LOGF_PrivOps, "Sent request op=%d", req->op);
 }
@@ -357,6 +366,26 @@ submit_request(PrvRequest *req, PrvResponse *res)
 
 /* ======================================================================= */
 
+/* DAEMON - send the helper a request to exit and wait until it exits */
+
+static void
+stop_helper(void)
+{
+  PrvRequest req;
+  int status;
+
+  if (!have_helper())
+    return;
+
+  memset(&req, 0, sizeof (req));
+  req.op = op_QUIT;
+  send_request(&req);
+
+  wait(&status);
+}
+
+/* ======================================================================= */
+
 /* DAEMON - request adjtime() */
 
 #ifdef PRIVOPS_ADJUSTTIME
@@ -489,6 +518,9 @@ PRV_Initialise(void)
     /* parent process */
     close(sock_pair[1]);
     helper_fd = sock_pair[0];
+
+    /* stop the helper even when not exiting cleanly from the main function */
+    atexit(stop_helper);
   }
 }
 
@@ -499,9 +531,10 @@ PRV_Initialise(void)
 void
 PRV_Finalise(void)
 {
-  int status;
+  if (!have_helper())
+    return;
 
+  stop_helper();
   close(helper_fd);
   helper_fd = -1;
-  wait(&status);
 }