/* The notifier socket has something to read. Pull the message from it, decode
and do the action.
+*/
-Return TRUE if a sigalrm should be emulated */
-
-static BOOL
+static void
daemon_notification(void)
{
uschar buf[256], cbuf[256];
ssize_t sz;
buf[sizeof(buf)-1] = 0;
-if ((sz = recvmsg(daemon_notifier_fd, &msg, 0)) <= 0) return FALSE;
-if (sz >= sizeof(buf)) return FALSE;
+if ((sz = recvmsg(daemon_notifier_fd, &msg, 0)) <= 0) return;
+if (sz >= sizeof(buf)) return;
#ifdef notdef
debug_printf("addrlen %d\n", msg.msg_namelen);
: !buf[1+MESSAGE_ID_LENGTH+1]
)
{ queuerun_msg_qname = q->name; break; }
- return TRUE;
+ return;
#endif
case NOTIFY_QUEUE_SIZE_REQ:
regex_at_daemon(buf);
break;
}
-return FALSE;
+return;
}
if (sorted)
{
qrunner ** p = &sorted;
- for (qrunner * qq; qq = *p; p = &(qq->next))
+ for (qrunner * qq; qq = *p; p = &qq->next)
if ( q->next_tick < qq->next_tick
|| q->next_tick == qq->next_tick && q->interval < qq->interval
)
return qrunners ? qrunners->next_tick - time(NULL) : 0;
}
+/* See if we can do a queue run. If policy limit permit, kick one off.
+If both notification and timer events are present, handle the former
+and leave the timer outstanding.
+
+Return the number of seconds until the next due runner.
+*/
+
static int
daemon_qrun(int local_queue_run_max, struct pollfd * fd_polls, int listen_socket_count)
{
enough queue runners on the go. If we are not running as root, a re-exec is
required. In the calling process, restart the alamr timer for the next run. */
-if (is_multiple_qrun())
+if (is_multiple_qrun()) /* we are managing periodic runs */
if (local_queue_run_max <= 0 || queue_run_count < local_queue_run_max)
{
qrunner * q = NULL;
#ifndef DISABLE_QUEUE_RAMP
- if (*queuerun_msgid) /* See if we can start another runner for this queue */
+ /* If this is a triggered run for a specific message, see if we can start
+ another runner for this queue. */
+
+ if (*queuerun_msgid)
{
for (qrunner * qq = qrunners; qq; qq = qq->next)
if (qq->name == queuerun_msg_qname)
}
else
#endif
- /* In order of run priority, find the first queue for which we can start
- a runner */
+ /* Normal periodic runL in order of run priority, find the first queue
+ for which we can start a runner */
for (q = qrunners; q; q = q->next)
if (q->run_count < q->run_max) break;
- if (q)
+ if (q) /* found a queue to run */
{
pid_t pid;
}
}
-sigalrm_seen = FALSE;
+/* The queue run has been initiated (unless we were already running enough) */
+
#ifndef DISABLE_QUEUE_RAMP
-if (*queuerun_msgid) /* it was a fast-ramp kick */
+if (*queuerun_msgid) /* it was a fast-ramp kick; dealt with */
*queuerun_msgid = 0;
else /* periodic or one-time queue run */
#endif
- { /* Impose a minimum 1s tick, even when a run was outstanding */
+ /* Set up next timer callback. Impose a minimum 1s tick,
+ even when a run was outstanding */
+ {
int interval = next_qrunner_interval();
if (interval <= 0) interval = 1;
+ sigalrm_seen = FALSE;
if (qrunners) /* there are still periodic qrunners */
{
- ALARM(interval);
+ ALARM(interval); /* set up next qrun tick */
return interval;
}
}
The other option is that we have an inetd wait timeout specified to -bw. */
- if (sigalrm_seen)
+ if (sigalrm_seen || *queuerun_msgid)
if (inetd_wait_timeout > 0)
daemon_inetd_wtimeout(last_connection_time); /* Might not return */
else
select() was interrupted so that we reap the child. This might still leave
a small window when a SIGCHLD could get lost. However, since we use SIGCHLD
only to do the reaping more quickly, it shouldn't result in anything other
- than a delay until something else causes a wake-up. */
+ than a delay until something else causes a wake-up.
+ For the normal case, wait for either a pollable fd (eg. new connection) or
+ or a SIGALRM (for a periodic queue run) */
if (sigchld_seen)
{
break; /* to top of daemon loop */
}
#endif
+ /* Handle the daemon-notifier socket. If it was a fast-ramp
+ notification then queuerun_msgid will have a nonzerolength string. */
+
if (dnotify_poll && dnotify_poll->revents & POLLIN)
{
dnotify_poll->revents = 0;
- sigalrm_seen = daemon_notification();
+ daemon_notification();
break; /* to top of daemon loop */
}
for (struct pollfd * p = fd_polls; p < fd_polls + listen_socket_count;