child-process.c revision 0c423a9cc14c5872f012be9640cb6e0d66a36717
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "lib-signals.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "hash.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "env-util.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "syslog-util.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "child-process.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include <unistd.h>
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include <syslog.h>
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include <sys/wait.h>
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainenconst char *process_names[PROCESS_TYPE_MAX] = {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "unknown",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "auth",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "auth-worker",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "login",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "imap",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "pop3",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "ssl-build-param",
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "dict"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen};
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstruct hash_table *processes;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstatic child_process_destroy_callback_t *destroy_callbacks[PROCESS_TYPE_MAX];
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainenstruct child_process *child_process_lookup(pid_t pid)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return hash_table_lookup(processes, POINTER_CAST(pid));
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid child_process_add(pid_t pid, struct child_process *process)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen hash_table_insert(processes, POINTER_CAST(pid), process);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenvoid child_process_remove(pid_t pid)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen hash_table_remove(processes, POINTER_CAST(pid));
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid child_process_init_env(void)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen int facility;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* remove all environment, we don't need them */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen env_clean();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen /* we'll log through master process */
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen env_put("LOG_TO_MASTER=1");
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (env_tz != NULL)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen env_put(t_strconcat("TZ=", env_tz, NULL));
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen if (settings_root == NULL ||
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen !syslog_facility_find(settings_root->defaults->syslog_facility,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen &facility))
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen facility = LOG_MAIL;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen env_put(t_strdup_printf("SYSLOG_FACILITY=%d", facility));
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (settings_root != NULL && !settings_root->defaults->version_ignore)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen env_put("DOVECOT_VERSION="PACKAGE_VERSION);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen#ifdef DEBUG
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (gdb) env_put("GDB=1");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainenvoid client_process_exec(const char *cmd, const char *title)
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen const char **argv;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen /* very simple argument splitting. */
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen if (*title == '\0')
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen argv = t_strsplit(cmd, " ");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen argv = t_strsplit(t_strconcat(cmd, " ", title, NULL), " ");
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen client_process_exec_argv(argv[0], argv);
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainenvoid client_process_exec_argv(const char *executable, const char **argv)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen const char *p;
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* hide the path, it's ugly */
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen p = strrchr(argv[0], '/');
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen if (p != NULL) argv[0] = p+1;
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen execv(executable, (char **)argv);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *get_exit_status_message(enum fatal_exit_status status,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen enum process_type process_type)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen switch (status) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case FATAL_LOGOPEN:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return "Can't open log file";
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case FATAL_LOGWRITE:
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return "Can't write to log file";
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen case FATAL_LOGERROR:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return "Internal logging error";
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen case FATAL_OUTOFMEM:
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen switch (process_type) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen case PROCESS_TYPE_AUTH:
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen case PROCESS_TYPE_AUTH_WORKER:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return "Out of memory - see auth_process_size setting";
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen case PROCESS_TYPE_LOGIN:
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return "Out of memory - see login_process_size setting";
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen case PROCESS_TYPE_IMAP:
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen case PROCESS_TYPE_POP3:
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return "Out of memory - see mail_process_size setting";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen case PROCESS_TYPE_UNKNOWN:
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen case PROCESS_TYPE_SSL_PARAM:
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen case PROCESS_TYPE_DICT:
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen case PROCESS_TYPE_MAX:
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return "Out of memory";
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen case FATAL_EXEC:
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return "exec() failed";
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen case FATAL_DEFAULT:
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return "Fatal failure";
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen return NULL;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstatic void
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenlog_coredump(string_t *str, enum process_type process_type, int status)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen{
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen#ifdef WCOREDUMP
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen int signum = WTERMSIG(status);
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (WCOREDUMP(status)) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen str_append(str, " (core dumped)");
4b41116563110d00330896a568eff1078c382827Timo Sirainen return;
4b41116563110d00330896a568eff1078c382827Timo Sirainen }
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (signum != SIGABRT && signum != SIGSEGV && signum != SIGBUS)
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen return;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* let's try to figure out why we didn't get a core dump */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (core_dumps_disabled) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen str_printfa(str, " (core dumps disabled)");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen }
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (process_type) {
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen case PROCESS_TYPE_LOGIN:
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen#ifdef HAVE_PR_SET_DUMPABLE
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen str_append(str, " (core not dumped - add -D to login_executable)");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen#else
cb05ecbd96ddb5e53c1850d27434541138a3f284Timo Sirainen break;
cb05ecbd96ddb5e53c1850d27434541138a3f284Timo Sirainen#endif
cb05ecbd96ddb5e53c1850d27434541138a3f284Timo Sirainen case PROCESS_TYPE_IMAP:
14ab4610b6038da6c5d0814fecabc6b74bc81a6bTimo Sirainen case PROCESS_TYPE_POP3:
14ab4610b6038da6c5d0814fecabc6b74bc81a6bTimo Sirainen#ifndef HAVE_PR_SET_DUMPABLE
14ab4610b6038da6c5d0814fecabc6b74bc81a6bTimo Sirainen if (!settings_root->defaults->mail_drop_priv_before_exec) {
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen str_append(str, " (core not dumped - set mail_drop_priv_before_exec=yes)");
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen return;
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainen }
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainen if (*settings_root->defaults->mail_privileged_group != '\0') {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen str_append(str, " (core not dumped - mail_privileged_group prevented it)");
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen return;
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen }
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen#endif
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen str_append(str, " (core not dumped - is home dir set?)");
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen return;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen case PROCESS_TYPE_AUTH:
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen case PROCESS_TYPE_AUTH_WORKER:
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (settings_root->auths->uid == 0)
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen break;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen#ifdef HAVE_PR_SET_DUMPABLE
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen str_printfa(str, " (core not dumped - "
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen "no permissions for auth user %s in %s?)",
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen settings_root->auths->user,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen settings_root->defaults->base_dir);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen#else
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen str_append(str, " (core not dumped - auth user is not root)");
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen#endif
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen break;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen str_append(str, " (core not dumped)");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#endif
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void sigchld_handler(const siginfo_t *si ATTR_UNUSED,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen void *context ATTR_UNUSED)
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct child_process *process;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *process_type_name, *msg;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum process_type process_type;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen string_t *str;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen pid_t pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int status;
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen bool abnormal_exit;
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen str = t_str_new(128);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* get the type and remove from hash */
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen str_truncate(str, 0);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen process = child_process_lookup(pid);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (process == NULL)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen process_type = PROCESS_TYPE_UNKNOWN;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen else {
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen process_type = process->type;
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen child_process_remove(pid);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen abnormal_exit = TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* write errors to syslog */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen process_type_name = process_names[process_type];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (WIFEXITED(status)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen status = WEXITSTATUS(status);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (status == 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen abnormal_exit = FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (process_type == PROCESS_TYPE_UNKNOWN) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_error("unknown child %s exited "
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "successfully", dec2str(pid));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen } else if (status == 1 &&
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen process_type == PROCESS_TYPE_SSL_PARAM) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* kludgy. hide this failure. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (status == FATAL_DEFAULT &&
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen process->seen_fatal) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* the error was already logged. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen msg = get_exit_status_message(status,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen process_type);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen msg = msg == NULL ? "" :
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen t_strconcat(" (", msg, ")", NULL);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen str_printfa(str,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen "child %s (%s) returned error %d%s",
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen dec2str(pid), process_type_name,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen status, msg);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen } else if (WIFSIGNALED(status)) {
64b5dcc136d6eb7ad90463e6cba9e16880ab52adTimo Sirainen str_printfa(str, "child %s (%s) killed with signal %d",
64b5dcc136d6eb7ad90463e6cba9e16880ab52adTimo Sirainen dec2str(pid), process_type_name,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen WTERMSIG(status));
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen log_coredump(str, process_type, status);
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen }
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen if (str_len(str) > 0) {
f23ede27743c1aa03eacbfc634d6a10de9110c91Timo Sirainen if (process != NULL && process->ip.family != 0) {
f23ede27743c1aa03eacbfc634d6a10de9110c91Timo Sirainen if (!process->ip_changed)
f23ede27743c1aa03eacbfc634d6a10de9110c91Timo Sirainen str_append(str, " (ip=");
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen else
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen str_append(str, " (latest ip=");
47001341950b8588c5f3a96b75864dab48e279aeTimo Sirainen str_printfa(str, "%s)",
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen net_ip2addr(&process->ip));
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen }
47001341950b8588c5f3a96b75864dab48e279aeTimo Sirainen i_error("%s", str_c(str));
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen }
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (destroy_callbacks[process_type] != NULL) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen destroy_callbacks[process_type](process, pid,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen abnormal_exit);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (pid == -1 && errno != EINTR && errno != ECHILD)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_warning("waitpid() failed: %m");
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenvoid child_process_set_destroy_callback(enum process_type type,
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen child_process_destroy_callback_t *cb)
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen{
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen i_assert(type < PROCESS_TYPE_MAX);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen destroy_callbacks[type] = cb;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen}
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainenvoid child_processes_init(void)
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen{
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen processes = hash_table_create(default_pool, default_pool, 128, NULL, NULL);
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen lib_signals_set_handler(SIGCHLD, TRUE, sigchld_handler, NULL);
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen}
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid child_processes_flush(void)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* make sure we log if child processes died unexpectedly */
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen sigchld_handler(NULL, NULL);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid child_processes_deinit(void)
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen child_processes_flush();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen lib_signals_unset_handler(SIGCHLD, sigchld_handler, NULL);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen hash_table_destroy(&processes);
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen}
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen