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