diff options
author | pjd <pjd@FreeBSD.org> | 2010-08-30 23:26:10 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2010-08-30 23:26:10 +0000 |
commit | 9b4ae63e7877da8b244dc4d6076cc57bc2f0ef20 (patch) | |
tree | 245f35c3193bdea89cf47c51960dd52a809d5f8e /sbin/hastd/hastd.c | |
parent | 8a7b72b9d3f5a419b8558fe232480453f6c4c070 (diff) | |
download | FreeBSD-src-9b4ae63e7877da8b244dc4d6076cc57bc2f0ef20.zip FreeBSD-src-9b4ae63e7877da8b244dc4d6076cc57bc2f0ef20.tar.gz |
Because it is very hard to make fork(2) from threaded process safe (we are
limited to async-signal safe functions in the child process), move all hooks
execution to the main (non-threaded) process.
Do it by maintaining connection (socketpair) between child and parent
and sending events from the child to parent, so it can execute the hook.
This is step in right direction for others reasons too. For example there is
one less problem to drop privs in worker processes.
MFC after: 2 weeks
Obtained from: Wheel Systems Sp. z o.o. http://www.wheelsystems.com
Diffstat (limited to 'sbin/hastd/hastd.c')
-rw-r--r-- | sbin/hastd/hastd.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index ccc25cf..6ddcbd2 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <pjdlog.h> #include "control.h" +#include "event.h" #include "hast.h" #include "hast_proto.h" #include "hastd.h" @@ -158,6 +159,11 @@ child_exit(void) role2str(res->hr_role)); child_exit_log(pid, status); proto_close(res->hr_ctrl); + res->hr_ctrl = NULL; + if (res->hr_event != NULL) { + proto_close(res->hr_event); + res->hr_event = NULL; + } res->hr_workerpid = 0; if (res->hr_role == HAST_ROLE_PRIMARY) { /* @@ -624,9 +630,10 @@ close: static void main_loop(void) { - fd_set rfds; - int cfd, lfd, maxfd, ret; + struct hast_resource *res; struct timeval timeout; + int fd, maxfd, ret; + fd_set rfds; timeout.tv_sec = REPORT_INTERVAL; timeout.tv_usec = 0; @@ -646,14 +653,20 @@ main_loop(void) hastd_reload(); } - cfd = proto_descriptor(cfg->hc_controlconn); - lfd = proto_descriptor(cfg->hc_listenconn); - maxfd = cfd > lfd ? cfd : lfd; - /* Setup descriptors for select(2). */ FD_ZERO(&rfds); - FD_SET(cfd, &rfds); - FD_SET(lfd, &rfds); + maxfd = fd = proto_descriptor(cfg->hc_controlconn); + FD_SET(fd, &rfds); + fd = proto_descriptor(cfg->hc_listenconn); + FD_SET(fd, &rfds); + maxfd = fd > maxfd ? fd : maxfd; + TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { + if (res->hr_event == NULL) + continue; + fd = proto_descriptor(res->hr_event); + FD_SET(fd, &rfds); + maxfd = fd > maxfd ? fd : maxfd; + } ret = select(maxfd + 1, &rfds, NULL, NULL, &timeout); if (ret == 0) @@ -665,10 +678,21 @@ main_loop(void) pjdlog_exit(EX_OSERR, "select() failed"); } - if (FD_ISSET(cfd, &rfds)) + if (FD_ISSET(proto_descriptor(cfg->hc_controlconn), &rfds)) control_handle(cfg); - if (FD_ISSET(lfd, &rfds)) + if (FD_ISSET(proto_descriptor(cfg->hc_listenconn), &rfds)) listen_accept(); + TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { + if (res->hr_event == NULL) + continue; + if (FD_ISSET(proto_descriptor(res->hr_event), &rfds)) { + if (event_recv(res) == 0) + continue; + /* The worker process exited? */ + proto_close(res->hr_event); + res->hr_event = NULL; + } + } } } |