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.
This commit is contained in:
Miroslav Lichvar 2015-12-08 11:10:52 +01:00
parent c7ae4940c3
commit 1b8ee3259e

View file

@ -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);
}