master-service.c revision 9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* when we're full of connections, how often to check if login state has
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen changed. we normally notice it immediately because of a signal, so this is
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen just a fallback against race conditions. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* If die callback hasn't managed to stop the service for this many seconds,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define MASTER_SERVICE_DIE_TIMEOUT_MSECS (30*1000)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void master_service_io_listeners_close(struct master_service *service);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void master_service_refresh_login_state(struct master_service *service);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return "c:i:ko:OL";
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* SIGINT comes either from master process or from keyboard. we don't
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen want to log it in either case.*/
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* never die when idling */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* SIGINT came from master. die only if we're not handling
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen any clients currently. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainensig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void master_service_verify_version_string(struct master_service *service)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen strcmp(service->version_string, PACKAGE_VERSION) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "(if you don't care, set version_ignore=yes)",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int *argc, char **argv[], const char *getopt_str)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* make sure we can dump core, at least until
non-setuid/gid binaries..) */
lib_init();
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();
return TRUE;
return TRUE;
return FALSE;
bool important_update;
used_count));
} T_END;
!important_update) {
service);
} else if (ret >= 0) {
} else if (important_update) {
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;