return 0;
}
-void service_signal(struct service *service, int signo)
+unsigned int service_signal(struct service *service, int signo,
+ unsigned int *uninitialized_count_r)
{
struct service_process *process = service->processes;
unsigned int count = 0;
+ *uninitialized_count_r = 0;
for (; process != NULL; process = process->next) {
i_assert(process->service == service);
if (!SERVICE_PROCESS_IS_INITIALIZED(process) &&
signo != SIGKILL) {
/* too early to signal it */
+ *uninitialized_count_r += 1;
continue;
}
signo == SIGTERM ? "SIGTERM" : "SIGKILL",
count, service->set->name);
}
+ return count;
}
static void service_login_notify_send(struct service *service)
{
+ unsigned int uninitialized_count;
+
service->last_login_notify_time = ioloop_time;
if (service->to_login_notify != NULL)
timeout_remove(&service->to_login_notify);
- service_signal(service, SIGUSR1);
+ service_signal(service, SIGUSR1, &uninitialized_count);
}
static void service_login_notify_timeout(struct service *service)
static void services_kill_timeout(struct service_list *service_list)
{
struct service *const *services, *log_service;
- bool sigterm_log;
+ unsigned int service_uninitialized, uninitialized_count = 0;
+ unsigned int signal_count = 0;
int sig;
- if (!service_list->sigterm_sent || !service_list->sigterm_sent_to_log)
+ if (!service_list->sigterm_sent)
sig = SIGTERM;
else
sig = SIGKILL;
- sigterm_log = service_list->sigterm_sent;
service_list->sigterm_sent = TRUE;
i_warning("Processes aren't dying after reload, sending %s.",
if (service->type == SERVICE_TYPE_LOG)
log_service = service;
- else
- service_signal(service, sig);
+ else {
+ signal_count += service_signal(service, sig,
+ &service_uninitialized);
+ uninitialized_count += service_uninitialized;
+ }
}
- /* kill log service later so it could still have a chance of logging
- something */
- if (log_service != NULL && sigterm_log) {
- service_signal(log_service, sig);
+ if (log_service == NULL) {
+ /* log service doesn't exist - shouldn't really happen */
+ } else if (signal_count > 0 || uninitialized_count > 0) {
+ /* kill log service later so the last remaining processes
+ can still have a chance of logging something */
+ } else {
+ if (!service_list->sigterm_sent_to_log)
+ sig = SIGTERM;
+ else
+ sig = SIGKILL;
service_list->sigterm_sent_to_log = TRUE;
+ signal_count += service_signal(log_service, sig, &service_uninitialized);
+ uninitialized_count += service_uninitialized;
}
}
/* Return path to configuration process socket. */
const char *services_get_config_socket_path(struct service_list *service_list);
-/* Send a signal to all processes in a given service */
-void service_signal(struct service *service, int signo);
+/* Send a signal to all processes in a given service. However, if we're sending
+ a SIGTERM and a process hasn't yet sent the initial status notification,
+ that process is skipped. The number of such skipped processes are stored in
+ uninitialized_count_r. Returns the number of processes that a signal was
+ successfully sent to. */
+unsigned int service_signal(struct service *service, int signo,
+ unsigned int *uninitialized_count_r);
/* Notify all processes (if necessary) that no more connections can be handled
by the service without killing existing connections (TRUE) or that they
can be (FALSE). */