master-service.c revision 53abc2e7d13e9bff7260f1a8513dc8aae3c68854
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen/* when we're full of connections, how often to check if login state has
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen changed. we normally notice it immediately because of a signal, so this is
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen just a fallback against race conditions. */
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen/* If die callback hasn't managed to stop the service for this many seconds,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define MASTER_SERVICE_DIE_TIMEOUT_MSECS (30*1000)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void master_service_io_listeners_close(struct master_service *service);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void master_service_refresh_login_state(struct master_service *service);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return "c:ko:Os:L";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* SIGINT comes either from master process or from keyboard. we don't
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen want to log it in either case.*/
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen /* never die when idling */
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen /* SIGINT came from master. die only if we're not handling
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainen any clients currently. */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainensig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void master_service_verify_version_string(struct master_service *service)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch strcmp(service->version_string, PACKAGE_VERSION) != 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen "(if you don't care, set version_ignore=yes)",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int *argc, char **argv[], const char *getopt_str)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen const char *str;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch /* make sure we can dump core, at least until
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen privileges are dropped. (i'm not really sure why this
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen is needed, because doing the same just before exec
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen doesn't help, and exec shouldn't affect this with
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen non-setuid/gid binaries..) */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* NOTE: we start rooted, so keep the code minimal until
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen restrict_access_by_env() is called */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* Set a logging prefix temporarily. This will be ignored once the log
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen is properly initialized */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* ignore these signals as early as possible */
return service;
const char *prefix)
const char *path;
int facility;
&facility))
bool set)
void (*callback)(void))
switch (opt) {
return FALSE;
return TRUE;
service);
const char *value;
unsigned int count;
count == 0)
count > 0)
#ifdef DEBUG
env_clean();
#ifdef DEBUG
unsigned int client_limit)
unsigned int used;
unsigned int count)
unsigned int used;
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;
!important_update) {
service);
} else if (ret >= 0) {
} else if (important_update) {
unsigned major_version)
bool ret;
return FALSE;
return FALSE;
T_BEGIN {
} T_END;
return ret;