master-service.c revision 047c00cd3f7f403672f81569413669238df8c15a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainenstatic void io_listeners_remove(struct master_service *service);
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainenstatic void master_status_update(struct master_service *service);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return "c:ko:Os:L";
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen which is too common at least while testing :) */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch lib_signal_code_to_str(si->si_signo, si->si_code));
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschstatic void master_service_verify_version(struct master_service *service)
04eb0abcf8f8b0c014499b5c5bae89484553613fStephan Bosch strcmp(service->version_string, PACKAGE_VERSION) != 0) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch "(if you don't care, set version_ignore=yes)",
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
529944a3554da75c2e6231a25fe489d815519b22Stephan Bosch const char *str;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* NOTE: we start rooted, so keep the code minimal until
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen restrict_access_by_env() is called */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* Set a logging prefix temporarily. This will be ignored once the log
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen is properly initialized */
fd3d068169c6ec587c9c446f2ee45560a444334aTimo Sirainen i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen service->service_count_left = (unsigned int)-1;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen service->config_path = getenv(MASTER_CONFIG_FILE_ENV);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen service->config_path = DEFAULT_CONFIG_FILE_PATH;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen service->version_string = getenv(MASTER_DOVECOT_VERSION_ENV);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* set up some kind of logging until we know exactly how and where
2b96880f2d789d125aff6a95eaa7b51f558a6a1cTimo Sirainen we want to log */
b84eff65e25ae86dfd6f798386577209b94838c6Timo Sirainen i_set_failure_prefix(t_strdup_printf("%s(%s): ",
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen i_set_failure_prefix(t_strdup_printf("%s: ", name));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid master_service_init_log(struct master_service *service,
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0 &&
325d17cdbb7a338f7c413788f5e8e42d2e80a7f8Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR) == 0) {
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen if (getenv("LOG_SERVICE") != NULL && !service->log_directly) {
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen /* logging via log service */
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen /* log to syslog */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (!syslog_facility_find(service->set->syslog_facility,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen /* log to file or stderr */
2dfd08e8aa16dfcc975d8a62bc8d20b2ef849d71Timo Sirainen path = home_expand(service->set->info_log_path);
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen path = home_expand(service->set->debug_log_path);
843640f0ca224bb9999acb290bca5f76037ab984Timo Sirainen i_set_failure_timestamp_format(service->set->log_timestamp);
02ccba3d3be96444abd15b5254864c9151bbeb30Timo Sirainenvoid master_service_set_die_with_master(struct master_service *service,
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainenbool master_service_parse_option(struct master_service *service,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (!array_is_created(&service->config_overrides))
56af9dd10e7e6caeaca64395bad3f882b28ecdffTimo Sirainen array_append(&service->config_overrides, &arg, 1);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen service->flags |= MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS;
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainenstatic void master_service_error(struct master_service *service)
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen service->total_available_count || service->die_with_master)
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen /* status fd is a write-only pipe, so if we're here it means the
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch master wants us to die (or died itself). don't die until all
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen service connections are finished. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* the log fd may also be closed already, don't die when trying to
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid master_service_init_finish(struct master_service *service)
c4ec7cb598805b1387dc3aab59ec8f32d8cc24e1Timo Sirainen unsigned int count;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(service->total_available_count == 0);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(service->service_count_left == (unsigned int)-1);
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen /* set default signal handlers */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen lib_signals_set_handler(SIGINT, TRUE, sig_die, service);
6a9e034441607c0c5a61858ff559af4615ac31caTimo Sirainen lib_signals_set_handler(SIGTERM, TRUE, sig_die, service);
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (fstat(MASTER_STATUS_FD, &st) < 0 || !S_ISFIFO(st.st_mode))
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("Must be started by dovecot master process");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* initialize master_status structure */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* set the default limit */
46ec792dd4ccf6c34706c4774228301fafde6aa9Timo Sirainen master_service_set_client_limit(service, count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* set the default service count */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen master_service_set_service_count(service, count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* start listening errors for status fd, it means master died */
2b96880f2d789d125aff6a95eaa7b51f558a6a1cTimo Sirainen service->io_status_error = io_add(MASTER_STATUS_FD, IO_ERROR,
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STD_CLIENT) != 0) {
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen /* we already have a connection to be served */
#ifdef DEBUG
env_clean();
#ifdef DEBUG
unsigned int client_limit)
unsigned int used;
unsigned int count)
unsigned int used;
void (*callback)(void))
if (ret < 0) {
} else if (ret == 0)
lib_deinit();
return TRUE;
return TRUE;
return FALSE;
if (ret > 0) {
} else if (ret == 0) {