#include "lib.h"
#include "ioloop.h"
#include "str.h"
+#include "network.h"
#include "backtrace-string.h"
#include "printf-format-fix.h"
#include "write-full.h"
log_stamp_format = i_strdup(fmt);
}
+void i_set_failure_ip(const struct ip_addr *ip)
+{
+ const char *str;
+
+ if (error_handler == i_internal_error_handler) {
+ str = t_strdup_printf("\x01Oip=%s\n", net_ip2addr(ip));
+ (void)write_full(2, str, strlen(str));
+ }
+}
+
void i_set_failure_exit_callback(void (*callback)(int *status))
{
failure_exit_callback = callback;
#ifndef FAILURES_H
#define FAILURES_H
+struct ip_addr;
+
/* Default exit status codes that we could use. */
enum fatal_exit_status {
FATAL_LOGOPEN = 80, /* Can't open log file */
/* Set the failure prefix. */
void i_set_failure_prefix(const char *prefix);
-
/* Prefix failures with a timestamp. fmt is in strftime() format. */
void i_set_failure_timestamp_format(const char *fmt);
+/* When logging with internal error protocol, update the process's current
+ IP address. This is mainly used by the master process to log some IP
+ address if the process crash. */
+void i_set_failure_ip(const struct ip_addr *ip);
/* Call the callback before exit()ing. The callback may update the status. */
void i_set_failure_exit_callback(void (*callback)(int *status));
i_error("accept() failed: %m");
return;
}
+ i_set_failure_ip(&remote_ip);
if (net_getsockname(fd, &local_ip, &local_port) < 0) {
memset(&local_ip, 0, sizeof(local_ip));
i_error("accept() failed: %m");
return;
}
+ i_set_failure_ip(&remote_ip);
if (net_getsockname(fd, &local_ip, &local_port) < 0) {
memset(&local_ip, 0, sizeof(local_ip));
bool have_initialized_auth_processes = FALSE;
static struct child_process auth_child_process =
- { PROCESS_TYPE_AUTH, 0 };
+ { MEMBER(type) PROCESS_TYPE_AUTH };
static struct child_process auth_worker_child_process =
- { PROCESS_TYPE_AUTH_WORKER, 0 };
+ { MEMBER(type) PROCESS_TYPE_AUTH_WORKER };
static struct timeout *to;
static unsigned int auth_tag;
#include "common.h"
#include "lib-signals.h"
#include "hash.h"
+#include "str.h"
#include "env-util.h"
#include "syslog-util.h"
#include "child-process.h"
struct child_process *process;
const char *process_type_name, *msg;
enum process_type process_type;
+ string_t *str;
pid_t pid;
int status;
bool abnormal_exit;
+ str = t_str_new(128);
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
/* get the type and remove from hash */
+ str_truncate(str, 0);
process = child_process_lookup(pid);
if (process == NULL)
process_type = PROCESS_TYPE_UNKNOWN;
process_type);
msg = msg == NULL ? "" :
t_strconcat(" (", msg, ")", NULL);
- i_error("child %s (%s) returned error %d%s",
- dec2str(pid), process_type_name,
- status, msg);
+ str_printfa(str,
+ "child %s (%s) returned error %d%s",
+ dec2str(pid), process_type_name,
+ status, msg);
}
} else if (WIFSIGNALED(status)) {
- i_error("child %s (%s) killed with signal %d",
- dec2str(pid), process_type_name,
- WTERMSIG(status));
+ str_printfa(str, "child %s (%s) killed with signal %d",
+ dec2str(pid), process_type_name,
+ WTERMSIG(status));
+ }
+
+ if (str_len(str) > 0) {
+ if (process != NULL && process->ip.family != 0) {
+ if (!process->ip_changed)
+ str_append(str, " (ip=");
+ else
+ str_append(str, " (latest ip=");
+ str_printfa(str, "%s)",
+ net_ip2addr(&process->ip));
+ }
+ i_error("%s", str_c(str));
}
if (destroy_callbacks[process_type] != NULL) {
struct child_process {
enum process_type type;
-
+ struct ip_addr ip;
+ unsigned int allow_change_ip:1;
unsigned int seen_fatal:1;
+ unsigned int ip_changed:1;
};
typedef void child_process_destroy_callback_t(struct child_process *process,
struct io *io;
struct istream *stream;
pid_t pid;
+ struct ip_addr ip;
time_t log_stamp;
unsigned int log_counter;
if (process != NULL)
process->seen_fatal = TRUE;
break;
+ case 'O':
+ /* logging option. ignore unknown ones. */
+ if (strncmp(line, "ip=", 3) == 0) {
+ process = child_process_lookup(log_io->pid);
+ if (process != NULL &&
+ (process->allow_change_ip ||
+ process->ip.family == 0)) {
+ if (process->ip.family != 0)
+ process->ip_changed = TRUE;
+ net_addr2ip(line + 3, &process->ip);
+ }
+ }
+ log_io->next_log_type = '\0';
+ return 1;
default:
log_type = LOG_TYPE_ERROR;
break;
p->io = io_add(fd, IO_READ, login_process_input, p);
p->output = o_stream_create_fd(fd, sizeof(struct master_login_reply)*10,
FALSE);
- if (!inetd_child)
+ if (!inetd_child) {
+ if (!group->set->login_process_per_connection)
+ p->process.allow_change_ip = TRUE;
child_process_add(pid, &p->process);
+ }
p->state = LOGIN_STATE_LISTENING;
#include <sys/stat.h>
static struct child_process ssl_param_child_process =
- { PROCESS_TYPE_SSL_PARAM, 0 };
+ { MEMBER(type) PROCESS_TYPE_SSL_PARAM };
static struct timeout *to;
static char *generating_path = NULL;