master-service.c revision 7f1b897201d80c83c96b0d663f2a14c517d48f14
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen/* when we're full of connections, how often to check if login state has
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen changed. we normally notice it immediately because of a signal, so this is
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen just a fallback against race conditions. */
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainen/* If die callback hasn't managed to stop the service for this many seconds,
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen#define MASTER_SERVICE_DIE_TIMEOUT_MSECS (30*1000)
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainenstatic void master_service_io_listeners_close(struct master_service *service);
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainenstatic void master_service_refresh_login_state(struct master_service *service);
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainen return "c:i:ko:OL";
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainen /* SIGINT comes either from master process or from keyboard. we don't
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainen want to log it in either case.*/
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen /* never die when idling */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen /* SIGINT came from master. die only if we're not handling
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen any clients currently. */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Boschsig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Boschstatic void master_service_verify_version_string(struct master_service *service)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch strcmp(service->version_string, PACKAGE_VERSION) != 0) {
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen "(if you don't care, set version_ignore=yes)",
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Boschmaster_service_init(const char *name, enum master_service_flags flags,
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch int *argc, char **argv[], const char *getopt_str)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch unsigned int count;
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* make sure we can dump core, at least until
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch privileges are dropped. (i'm not really sure why this
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch is needed, because doing the same just before exec
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch doesn't help, and exec shouldn't affect this with
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch non-setuid/gid binaries..) */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* NOTE: we start rooted, so keep the code minimal until
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch restrict_access_by_env() is called */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* Set a logging prefix temporarily. This will be ignored once the log
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch is properly initialized */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* ignore these signals as early as possible */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* keep getopt_str first in case it contains "+" */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch i_strconcat(getopt_str, master_service_getopt_string(), NULL);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch service->config_path = i_strdup(getenv(MASTER_CONFIG_FILE_ENV));
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch service->config_path = i_strdup(DEFAULT_CONFIG_FILE_PATH);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch service->version_string = getenv(MASTER_DOVECOT_VERSION_ENV);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch str_array_length((void *)service->listener_names);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch service->want_ssl_settings = service->ssl_socket_count > 0 ||
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch (flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* set up some kind of logging until we know exactly how and where
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch we want to log */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch i_set_failure_prefix("%s(%s): ", name, getenv("USER"));
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* initialize master_status structure */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch str_to_uint(value, &service->master_status.uid) < 0)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* set the default limit */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if (value == NULL || str_to_uint(value, &count) < 0 ||
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch master_service_set_client_limit(service, count);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* seve the process limit */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if (value != NULL && str_to_uint(value, &count) == 0 &&
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if (value != NULL && str_to_uint(value, &count) == 0 &&
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* set the default service count */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if (value != NULL && str_to_uint(value, &count) == 0 &&
return service;
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;