master-service.c revision 13f4d4d4a69d7dff2f71363d189d048abb04b6c6
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen/* when we're full of connections, how often to check if login state has
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen changed. we normally notice it immediately because of a signal, so this is
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen just a fallback against race conditions. */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen/* If die callback hasn't managed to stop the service for this many seconds,
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen#define MASTER_SERVICE_DIE_TIMEOUT_MSECS (30*1000)
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainenstatic void master_service_io_listeners_close(struct master_service *service);
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainenstatic void master_service_refresh_login_state(struct master_service *service);
7a62083331fbbb73121d16d6e13fc3dbc5720aa7Timo Sirainenmaster_status_send(struct master_service *service, bool important_update);
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen return "c:i:ko:OL";
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
7a62083331fbbb73121d16d6e13fc3dbc5720aa7Timo Sirainen /* SIGINT comes either from master process or from keyboard. we don't
7a62083331fbbb73121d16d6e13fc3dbc5720aa7Timo Sirainen want to log it in either case.*/
7a62083331fbbb73121d16d6e13fc3dbc5720aa7Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
7a62083331fbbb73121d16d6e13fc3dbc5720aa7Timo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen /* never die when idling */
ec23a602b0230eea29e64e2f283a9cf215be1f82Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
ec23a602b0230eea29e64e2f283a9cf215be1f82Timo Sirainen /* SIGINT came from master. die only if we're not handling
ec23a602b0230eea29e64e2f283a9cf215be1f82Timo Sirainen any clients currently. */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen /* we don't want to die - send a notification to master
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen so it doesn't think we're ignoring it completely. */
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainensig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainenstatic void master_service_verify_version_string(struct master_service *service)
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen strcmp(service->version_string, PACKAGE_VERSION) != 0) {
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen "(if you don't care, set version_ignore=yes)",
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenstatic void master_service_init_socket_listeners(struct master_service *service)
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen unsigned int i;
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen i_new(struct master_service_listener, service->socket_count);
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen struct master_service_listener *l = &service->listeners[i];
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen value = getenv(t_strdup_printf("SOCKET%u_SETTINGS", i));
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen const char *const *settings =
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen } else if (strcmp(*settings, "haproxy") == 0) {
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen service->want_ssl_settings = have_ssl_sockets ||
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen (service->flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen int *argc, char **argv[], const char *getopt_str)
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen unsigned int count;
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
non-setuid/gid binaries..) */
lib_init();
T_BEGIN {
} T_END;
count == 0)
count > 0)
count > 0)
count > 0)
return service;
return FALSE;
return TRUE;
const char *prefix)
int facility;
&facility))
bool set)
void (*callback)(void))
bool (*callback)(void))
which dovecot.conf we even want to read! so we must use the
const char *path;
switch (opt) {
return FALSE;
return TRUE;
service);
void master_service_env_clean(void)
env_clean();
else T_BEGIN {
} T_END;
unsigned int client_limit)
unsigned int used;
unsigned int count)
unsigned int used;
int listen_fd)
void (*callback)(void))
unsigned int current_count;
if (current_count == 0)
if (ret < 0) {
} else if (ret == 0)
switch (state) {
service);
case MASTER_LOGIN_STATE_FULL:
int ret;
if (ret < 0)
lib_deinit();
if (l->haproxy)
return TRUE;
return TRUE;
return FALSE;
} else if (ret >= 0) {
} else if (important_update) {
bool important_update;
used_count));
} T_END;
!important_update) {
service);
unsigned major_version)
unsigned int minor_version;
unsigned major_version,
unsigned int *minor_version_r)
bool ret;
return FALSE;
return FALSE;
T_BEGIN {
if (p == NULL)
} T_END;
return ret;