service-process.c revision 114162093a3eb36c23a4ce4d4f2a43541dc18cc2
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen unsigned int i, count, n = 0, socket_listener_count, ssl_socket_count;
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen /* stdin/stdout is already redirected to /dev/null. Other master fds
a87ee34b90aa7bb236751803c292c4deb6cfb058Timo Sirainen should have been opened with fd_close_on_exec() so we don't have to
a87ee34b90aa7bb236751803c292c4deb6cfb058Timo Sirainen worry about them.
a87ee34b90aa7bb236751803c292c4deb6cfb058Timo Sirainen because the destination fd might be another one's source fd we have
a87ee34b90aa7bb236751803c292c4deb6cfb058Timo Sirainen to be careful not to overwrite anything. dup() the fd when needed */
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen listeners = array_get(&service->listeners, &count);
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen services_log_dup2(&dups, service->list, MASTER_LISTEN_FD_FIRST,
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen /* nonblocking anvil fd must be the first one. anvil treats it
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen as the master's fd */
06843a896589e98fb259e6d7558326655126a407Timo Sirainen dup2_append(&dups, service_anvil_global->nonblocking_fd[0],
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen dup2_append(&dups, service_anvil_global->blocking_fd[0],
4a6f9ed8e5412508dcba1eabb58a3680ad5e9b68Timo Sirainen /* first add non-ssl listeners */
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen for (i = 0; i < count; i++) {
6b35ba747072480bfc86ed7cc69df1d418e2ae20Timo Sirainen (listeners[i]->type != SERVICE_LISTENER_INET ||
6b35ba747072480bfc86ed7cc69df1d418e2ae20Timo Sirainen /* then ssl-listeners */
6b35ba747072480bfc86ed7cc69df1d418e2ae20Timo Sirainen for (i = 0; i < count; i++) {
6b35ba747072480bfc86ed7cc69df1d418e2ae20Timo Sirainen listeners[i]->type == SERVICE_LISTENER_INET &&
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen dup2_append(&dups, service_anvil_global->blocking_fd[1],
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen /* set log file to stderr. dup2() here immediately so that
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen we can set up logging to it without causing any log messages
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen to be lost. */
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen if (dup2(service->log_fd[1], STDERR_FILENO) < 0)
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen /* make sure we don't leak syslog fd. try to do it as late as possible,
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen but also before dup2()s in case syslog fd is one of them. */
51aceed49d7edcf1ce385d6d97f0acb7067a6608Aki Tuomi i_fatal("service(%s): dup2s failed", service->set->name);
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen unsigned int len;
146e7e3fabdd843d50680cdb6e4f7829890f5fcfTimo Sirainen restrict_process_size(service->vsz_limit/1024, -1U);
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen rset.privileged_gid = service->privileged_gid;
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen rset.chroot_dir = *service->set->chroot == '\0' ? NULL :
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen /* drop trailing / if it exists */
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen rset.chroot_dir = t_strndup(rset.chroot_dir, len-1);
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen disallow_root = service->type == SERVICE_TYPE_LOGIN;
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainenservice_process_setup_environment(struct service *service, unsigned int uid)
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen const struct master_service_settings *set = service->list->service_set;
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen const char *const *p;
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen /* remove all environment, and put back what we need */
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen for (p = service->list->child_process_env; *p != NULL; p++)
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen /* give the log's configuration directly, so it won't depend
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen on config process */
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen env_put(t_strconcat("LOG_PATH=", set->log_path, NULL));
047ebb958b682bc058097eddc34df574c3f3d6d4Timo Sirainen env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
60212a51eb0e34a90fd3416a8a6c0047814ee968Timo Sirainen services_get_config_socket_path(service->list), NULL));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strdup_printf(MASTER_CLIENT_LIMIT_ENV"=%u",
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strdup_printf(MASTER_SERVICE_COUNT_ENV"=%u",
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid));
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen if (!service->set->master_set->version_ignore)
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION);
51aceed49d7edcf1ce385d6d97f0acb7067a6608Aki Tuomi if (*ssl_manual_key_password != '\0' && service->have_inet_listeners) {
51aceed49d7edcf1ce385d6d97f0acb7067a6608Aki Tuomi /* manually given SSL password. give it only to services
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen that have inet listeners. */
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen env_put(t_strconcat(MASTER_SSL_KEY_PASSWORD_ENV"=",
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainenstatic void service_process_status_timeout(struct service_process *process)
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen "Initial status notification not received in %d "
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen "seconds, killing the process",
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen if (kill(process->pid, SIGKILL) < 0 && errno != ESRCH) {
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen service_error(process->service, "kill(%s, SIGKILL) failed: %m",
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainenstruct service_process *service_process_create(struct service *service)
03b33ccb012636e453189ceef3865dee7812392eTimo Sirainen static unsigned int uid_counter = 0;
6ea49f0ffe92ac0d709ac9282e136a94df0053eeTimo Sirainen /* throttling service, don't create new processes */
7de17a595a44e61714d3fc7e55491449d38a8e62Timo Sirainen service_process_setup_environment(service, uid);
7de17a595a44e61714d3fc7e55491449d38a8e62Timo Sirainen timeout_add(SERVICE_FIRST_STATUS_TIMEOUT_SECS * 1000,
7de17a595a44e61714d3fc7e55491449d38a8e62Timo Sirainen process->available_count = service->client_limit;
7de17a595a44e61714d3fc7e55491449d38a8e62Timo Sirainen hash_table_insert(service_pids, &process->pid, process);
8d85926bc5484cf5f8de2ab3218298fe01d62696Timo Sirainen if (service->type == SERVICE_TYPE_ANVIL && process_forked)
8d85926bc5484cf5f8de2ab3218298fe01d62696Timo Sirainenvoid service_process_destroy(struct service_process *process)
8d85926bc5484cf5f8de2ab3218298fe01d62696Timo Sirainen struct service_list *service_list = service->list;
8d85926bc5484cf5f8de2ab3218298fe01d62696Timo Sirainen hash_table_remove(service_pids, &process->pid);
return TRUE;
return FALSE;
switch (status) {
case FATAL_LOGOPEN:
case FATAL_LOGWRITE:
case FATAL_LOGERROR:
case FATAL_OUTOFMEM:
case FATAL_EXEC:
case FATAL_DEFAULT:
return NULL;
#ifdef WCOREDUMP
if (core_dumps_disabled) {
#ifndef HAVE_PR_SET_DUMPABLE
const char *msg;
if (status == 0) {
const char *data;
int status)
T_BEGIN {
bool default_fatal;
} T_END;