From 1b8ee3259ee42ec0fbc71eaac2aeb448a4abfcd6 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 8 Dec 2015 11:10:52 +0100 Subject: [PATCH] privops: stop helper on exit 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 | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/privops.c b/privops.c index f5ad8f2..439b10a 100644 --- 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); }