From: Miroslav Lichvar Date: Tue, 8 Dec 2015 10:10:52 +0000 (+0100) Subject: privops: stop helper on exit X-Git-Tag: 2.3-pre1~70 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b8ee3259ee42ec0fbc71eaac2aeb448a4abfcd6;p=thirdparty%2Fchrony.git 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. --- diff --git a/privops.c b/privops.c index f5ad8f20..439b10af 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); }