service-process.c revision 077ab4470660b791c2b76eb4bb5663bbafc8177f
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic void service_reopen_inet_listeners(struct service *service)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi unsigned int i, count;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi listeners = array_get(&service->listeners, &count);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (i = 0; i < count; i++) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (!listeners[i]->reuse_port || listeners[i]->fd == -1)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (service_listener_listen(listeners[i]) < 0)
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi unsigned int i, count, socket_listener_count, ssl_socket_count;
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* stdin/stdout is already redirected to /dev/null. Other master fds
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi should have been opened with fd_close_on_exec() so we don't have to
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi worry about them.
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi because the destination fd might be another one's source fd we have
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi to be careful not to overwrite anything. dup() the fd when needed */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi listeners = array_get(&service->listeners, &count);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* nonblocking anvil fd must be the first one. anvil treats it
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi as the master's fd */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, service_anvil_global->nonblocking_fd[0], fd++);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, service_anvil_global->blocking_fd[0], fd++);
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* anvil/log fds have no names */
48e49f08c0f0d33d75e42cd1f6bf446f740fff8aKATOH Yasufumi for (i = MASTER_LISTEN_FD_FIRST; i < (unsigned int)fd; i++)
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi /* first add non-ssl listeners */
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi for (i = 0; i < count; i++) {
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi (listeners[i]->type != SERVICE_LISTENER_INET ||
48e49f08c0f0d33d75e42cd1f6bf446f740fff8aKATOH Yasufumi str_append_tabescaped(listener_names, listeners[i]->name);
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* then ssl-listeners */
e8ea311657f82b91710dfcb8bca656bd5b94c66cKATOH Yasufumi for (i = 0; i < count; i++) {
e8ea311657f82b91710dfcb8bca656bd5b94c66cKATOH Yasufumi listeners[i]->type == SERVICE_LISTENER_INET &&
e8ea311657f82b91710dfcb8bca656bd5b94c66cKATOH Yasufumi str_append_tabescaped(listener_names, listeners[i]->name);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, null_fd, MASTER_ANVIL_FD);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, service_anvil_global->blocking_fd[1],
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dup2_append(&dups, service->list->master_dead_pipe_fd[1],
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi dup2_append(&dups, global_master_dead_pipe_fd[1],
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* keep stderr as-is. this is especially important when
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi log_path=/dev/stderr, but might be helpful even in other
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi situations for logging startup errors */
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* set log file to stderr. dup2() here immediately so that
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi we can set up logging to it without causing any log messages
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi to be lost. */
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi if (dup2(service->log_fd[1], STDERR_FILENO) < 0)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* make sure we don't leak syslog fd. try to do it as late as possible,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi but also before dup2()s in case syslog fd is one of them. */
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi i_fatal("service(%s): dup2s failed", service->set->name);
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi i_assert(fd == MASTER_LISTEN_FD_FIRST + (int)socket_listener_count);
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
99282c429a23a2ffa699ca149bb7f9cd5705646aKATOH Yasufumi env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strdup_printf("SOCKET_NAMES=%s", str_c(listener_names)));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi unsigned int len;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi rset.privileged_gid = service->privileged_gid;
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi rset.chroot_dir = *service->set->chroot == '\0' ? NULL :
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* drop trailing / if it exists */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi rset.chroot_dir = t_strndup(rset.chroot_dir, len-1);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi disallow_root = service->type == SERVICE_TYPE_LOGIN;
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumistatic void service_process_setup_config_environment(struct service *service)
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi const struct master_service_settings *set = service->list->service_set;
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* give the log's configuration directly, so it won't depend
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi on config process */
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strconcat("LOG_PATH=", set->log_path, NULL));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL));
f7f1ba77b76e4d4dc18638cfdc859c3dc1750a9eStéphane Graber env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi services_get_config_socket_path(service->list), NULL));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumiservice_process_setup_environment(struct service *service, unsigned int uid)
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi service_process_setup_config_environment(service);
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi env_put(t_strdup_printf(MASTER_CLIENT_LIMIT_ENV"=%u",
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi env_put(t_strdup_printf(MASTER_PROCESS_LIMIT_ENV"=%u",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strdup_printf(MASTER_PROCESS_MIN_AVAIL_ENV"=%u",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strdup_printf(MASTER_SERVICE_IDLE_KILL_ENV"=%u",
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strdup_printf(MASTER_SERVICE_COUNT_ENV"=%u",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi env_put(t_strdup_printf(MY_HOSTNAME_ENV"=%s", my_hostname));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi env_put(t_strdup_printf(MY_HOSTDOMAIN_ENV"=%s", my_hostdomain()));
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi if (!service->set->master_set->version_ignore)
48e49f08c0f0d33d75e42cd1f6bf446f740fff8aKATOH Yasufumi env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION);
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi if (ssl_manual_key_password != NULL && service->have_inet_listeners) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* manually given SSL password. give it only to services
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi that have inet listeners. */
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi env_put(t_strconcat(MASTER_SSL_KEY_PASSWORD_ENV"=",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic void service_process_status_timeout(struct service_process *process)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "Initial status notification not received in %d "
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "seconds, killing the process",
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi if (kill(process->pid, SIGKILL) < 0 && errno != ESRCH) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi service_error(process->service, "kill(%s, SIGKILL) failed: %m",
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumistruct service_process *service_process_create(struct service *service)
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi static unsigned int uid_counter = 0;
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi /* throttling service, don't create new processes */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* these services are being destroyed, no point in creating
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi new processes now */
9a97d4e4bdf331bb2c2b8ed14bcefa53358c288fKATOH Yasufumi service_process_setup_environment(service, uid);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi timeout_add(SERVICE_FIRST_STATUS_TIMEOUT_SECS * 1000,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi process->available_count = service->client_limit;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DLLIST_PREPEND(&service->processes, process);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi hash_table_insert(service_pids, POINTER_CAST(process->pid), process);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (service->type == SERVICE_TYPE_ANVIL && process_forked)
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;