diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/diag.c | 1 | ||||
-rw-r--r-- | src/meta1gram.y | 1 | ||||
-rw-r--r-- | src/pies.c | 12 | ||||
-rw-r--r-- | src/pies.h | 10 | ||||
-rw-r--r-- | src/progman.c | 10 | ||||
-rw-r--r-- | src/socket.c | 146 |
6 files changed, 113 insertions, 67 deletions
@@ -28,6 +28,7 @@ syslog_printer (int prio, const char *fmt, va_list ap) #else char buf[128]; vsnprintf (buf, sizeof buf, fmt, ap); + syslog (prio, "%s", buf); #endif } diff --git a/src/meta1gram.y b/src/meta1gram.y index db92d61..5fa143b 100644 --- a/src/meta1gram.y +++ b/src/meta1gram.y @@ -365,7 +365,6 @@ meta1_translate (struct meta1_stmt *stmt) } comp->privs.allgroups = 1; comp->dir = META1_QUEUE_DIR (); - comp->settle_timeout = 1; comp->redir[RETR_ERR].type = redir_file; comp->redir[RETR_ERR].v.file = xasprintf ("%s/%s.log", META1_QUEUE_DIR (), @@ -776,11 +776,11 @@ struct grecs_keyword component_keywords[] = { grecs_type_bool, NULL, offsetof (struct component, disabled), NULL, }, - {"settle-timeout", + {"pass-fd-timeout", NULL, - N_("Time to wait before starting this component."), + N_("Time to wait for pass-fd socket to become available."), grecs_type_uint, NULL, - offsetof (struct component, settle_timeout), + offsetof (struct component, pass_fd_timeout), NULL, }, {"precious", @@ -1856,6 +1856,9 @@ main (int argc, char **argv) exit (EX_USAGE); } + if (!foreground) + log_setup (log_to_stderr = 0); + logmsg (LOG_INFO, _("%s starting"), program_version); if (!foreground) @@ -1917,9 +1920,10 @@ main (int argc, char **argv) if (action == ACTION_RESTART && argv[0][0] == '/') { + int minfd = log_to_stderr ? 2 : 0; int i; - for (i = getmaxfd (); i > 0; i--) + for (i = getmaxfd (); i > minfd; i--) close (i); remove_pidfile (pidfile); @@ -61,6 +61,8 @@ #define SLEEPTIME 5*60 #define MAXSPAWN 10 +#define DEFAULT_PASS_FD_TIMEOUT 5 + #define RETR_OUT 0 #define RETR_ERR 1 @@ -134,7 +136,7 @@ enum pies_comp_mode struct component { - enum pies_comp_mode mode; + enum pies_comp_mode mode; char *tag; /* Entry tag (for diagnostics purposes) */ char *program; /* Program name */ char **argv; /* Program command line */ @@ -142,8 +144,6 @@ struct component char *dir; /* Working directory */ gl_list_t prereq; /* Prerequisites */ gl_list_t depend; /* Dependency targets */ - unsigned settle_timeout; /* Time needed for started prerequisites to - settle */ /* FIXME: disabled and precious can be encoded as bits in mode */ int disabled; /* The componenet is disabled */ int precious; /* The component is precious (cannot be disabled) */ @@ -155,6 +155,8 @@ struct component (if mode != pies_comp_exec) */ char *pass_fd_socket; /* Socket to pass fd on (if mode == pies_comp_pass_fd) */ + unsigned pass_fd_timeout; /* Maximum time to wait for pass_fd socket to + become available. */ pies_acl_t acl; /* Redirectors: */ int facility; /* Syslog facility. */ @@ -239,7 +241,7 @@ const char * pies_url_get_arg (struct pies_url *url, const char *argname); void pies_pause (void); int register_listener (int fd); -int pass_fd (const char *socket, int fd); +int pass_fd (const char *socket, int fd, unsigned time_out); int create_socket (struct pies_url *url, const char *user, mode_t umask); diff --git a/src/progman.c b/src/progman.c index 7438837..cc107f7 100644 --- a/src/progman.c +++ b/src/progman.c @@ -773,8 +773,9 @@ prog_start (struct prog *prog) default: if (prog->v.p.comp->mode == pies_comp_pass_fd) { - sleep(1); - pass_fd (prog->v.p.comp->pass_fd_socket, prog->v.p.socket); + pass_fd (prog->v.p.comp->pass_fd_socket, prog->v.p.socket, + prog->v.p.comp->pass_fd_timeout ? + prog->v.p.comp->pass_fd_timeout : DEFAULT_PASS_FD_TIMEOUT); /* FIXME: Error code */; } if (prog->v.p.comp->mode != pies_comp_exec) @@ -1164,7 +1165,6 @@ prog_start_prerequisites (struct prog *prog) { int i; int ret; - unsigned settle_timeout = 0; if (!prog->prereq) return 0; /* Ok to startup */ @@ -1203,11 +1203,7 @@ prog_start_prerequisites (struct prog *prog) prog_start (prog_lookup_by_tag (prog->prereq[i])); if (!(dp->v.p.status == status_enabled && dp->pid)) ret = 1; - else - settle_timeout = prog->v.p.comp->settle_timeout; } - if (ret == 0 && settle_timeout) - sleep (settle_timeout); return ret; } diff --git a/src/socket.c b/src/socket.c index 8f32ae7..1aa1256 100644 --- a/src/socket.c +++ b/src/socket.c @@ -249,37 +249,6 @@ create_socket (struct pies_url *url, const char *user, mode_t umaskval) } static int -open_unix_socket (const char *socket_name) -{ - int fd; - struct sockaddr_un addr; - - if (strlen (socket_name) > sizeof addr.sun_path) - { - logmsg (LOG_ERR, _("%s: UNIX socket name too long"), socket_name); - return -1; - } - - fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - logmsg (LOG_ERR, "socket: %s", strerror (errno)); - return -1; - } - addr.sun_family = AF_UNIX; - strcpy (addr.sun_path, socket_name); - - if (connect (fd, (struct sockaddr *) &addr, sizeof (addr))) - { - logmsg (LOG_ERR, _("%s: connect failed: %s"), socket_name, strerror (errno)); - close (fd); - return -1; - } - - return fd; -} - -static int pass_fd0 (int fd, int payload) { struct msghdr msg; @@ -324,40 +293,115 @@ pass_fd0 (int fd, int payload) } int -pass_fd (const char *socket, int fd) +pass_fd (const char *socket_name, int fd, unsigned maxtime) { - int i; - struct stat st; + enum { fds_init, fds_open, fds_connected, fds_ready } state = fds_init; + static char *fds_descr[] = { "init", "open", "connected", "ready" }; + time_t start = time (NULL); + int sockfd = -1; + int res = -1; + struct sockaddr_un addr; - for (i = 0; i < 10; i++) + if (strlen (socket_name) > sizeof addr.sun_path) { - if (stat (socket, &st) == 0) + logmsg (LOG_ERR, _("%s: UNIX socket name too long"), socket_name); + return -1; + } + addr.sun_family = AF_UNIX; + strcpy (addr.sun_path, socket_name); + + for (;;) + { + time_t now = time (NULL); + + if (now - start > maxtime) { - int rc; - int sockfd; - - if (!S_ISSOCK (st.st_mode)) + logmsg (LOG_ERR, _("pass-fd timed out in state %s"), + fds_descr[state]); + break; + } + + if (state == fds_init) + { + struct stat st; + + if (stat (socket_name, &st) == 0) + { + if (!S_ISSOCK (st.st_mode)) + { + logmsg (LOG_ERR, _("%s: not a socket"), socket_name); + break; + } + + sockfd = socket (PF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) + { + if (errno == EINTR) + continue; + logmsg (LOG_ERR, "socket: %s", strerror (errno)); + break; + } + state = fds_open; + } + else if (errno != ENOENT) { - logmsg (LOG_ERR, _("%s: not a socket"), socket); + logmsg (LOG_ERR, _("cannot stat %s: %s"), + socket_name, strerror (errno)); break; } - sockfd = open_unix_socket (socket); - if (sockfd == -1) - rc = 1; - else + } + + if (state == fds_open) + { + if (connect (sockfd, (struct sockaddr *) &addr, sizeof (addr))) + { + switch (errno) + { + case EINTR: + case ECONNREFUSED: + case EAGAIN: + continue; + } + logmsg (LOG_ERR, _("%s: connect failed: %s"), + socket_name, strerror (errno)); + break; + } + state = fds_connected; + } + + if (state == fds_connected) + { + int rc; + fd_set fds; + struct timeval tv; + + FD_ZERO (&fds); + FD_SET (sockfd, &fds); + tv.tv_usec = 0; + tv.tv_sec = maxtime - (now - start); + rc = select (sockfd + 1, NULL, &fds, NULL, &tv); + if (rc == 0) + continue; + if (rc < 0) { - rc = pass_fd0 (sockfd, fd); - close (sockfd); + if (errno == EINTR) + continue; + logmsg (LOG_ERR, _("select failed: %s"), strerror (errno)); + break; } - return rc; + state = fds_ready; } - if (errno != ENOENT) + + if (state == fds_ready) { - logmsg (LOG_ERR, _("cannot stat %s: %s"), socket, strerror (errno)); + res = pass_fd0 (sockfd, fd); break; } } - return -1; + + if (sockfd >= 0) + close (sockfd); + return res; } |