log-connection.c revision 0dffa25d211be541ee3c953b23566a1a990789df
/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "istream.h"
#include "llist.h"
#include "hash.h"
#include "time-util.h"
#include "process-title.h"
#include "master-interface.h"
#include "master-service.h"
#include "log-error-buffer.h"
#include "log-connection.h"
#include <stdio.h>
#include <unistd.h>
#define FATAL_QUEUE_TIMEOUT_MSECS 500
#define MAX_MSECS_PER_CONNECTION 100
/* Log a warning after 1 secs when we've been all the time busy writing the
log connection. */
/* If we keep beeing busy, log a warning every 60 seconds. */
struct log_client {
char *prefix;
bool fatal_logged:1;
};
struct log_connection {
struct log_error_buffer *errorbuf;
int fd;
int listen_fd;
char *default_prefix;
unsigned int pending_count;
bool master:1;
bool handshaked:1;
};
static unsigned int global_pending_count;
static struct log_connection *last_pending_log;
static void log_refresh_proctitle(void)
{
if (!verbose_proctitle)
return;
if (global_pending_count == 0)
process_title_set("");
else if (last_pending_log == NULL) {
"[%u services too fast]", global_pending_count));
} else if (global_pending_count > 1) {
"[%u services too fast, last: %d/%d/%s]",
} else {
"[service too fast: %d/%d/%s]",
}
}
{
struct log_client *client;
}
return client;
}
{
}
const struct failure_line *failure)
{
struct log_client *client;
}
}
static void
const struct failure_context *ctx,
{
case LOG_TYPE_DEBUG:
case LOG_TYPE_INFO:
case LOG_TYPE_COUNT:
case LOG_TYPE_OPTION:
break;
case LOG_TYPE_WARNING:
case LOG_TYPE_ERROR:
case LOG_TYPE_FATAL:
case LOG_TYPE_PANIC:
break;
}
i_set_failure_prefix("log: ");
}
static void
{
struct failure_context failure_ctx;
}
}
}
static void
{
struct log_client *client;
unsigned int count;
unsigned int service_fd;
return;
}
return;
}
/* master is probably shutting down and we already
noticed the log fd closing */
return;
}
i_error("Received master input for invalid service_fd %u: %s",
service_fd, line);
return;
}
/* we haven't seen anything important from this client.
it's not an error. */
return;
}
message. */
} else {
}
}
static void
{
struct failure_line failure;
struct failure_context failure_ctx;
const char *prefix;
T_BEGIN {
} T_END;
return;
}
case LOG_TYPE_FATAL:
case LOG_TYPE_PANIC:
}
break;
case LOG_TYPE_OPTION:
return;
default:
break;
}
}
{
struct log_service_handshake handshake;
const unsigned char *data;
if (ret < 0) {
return -1;
}
/* this isn't a handshake */
return 0;
}
/* this isn't a handshake */
return 0;
}
i_error("Missing prefix data in handshake");
return -1;
}
i_error("Received master prefix in handshake "
return -1;
}
}
return 0;
}
{
const char *line;
if (!log->handshaked) {
if (log_connection_handshake(log) < 0) {
return;
}
}
/* get new timestamps for every read() */
break;
}
}
} else {
if (!too_much) {
if (log->pending_count > 0) {
log->pending_count = 0;
i_assert(global_pending_count > 0);
if (log == last_pending_log)
}
return;
}
if (log->pending_count++ == 0) {
}
i_warning("Log connection fd %d listen_fd %d prefix '%s' is sending input faster than we can write",
}
}
}
{
struct log_connection *log;
}
{
struct hash_iterate_context *iter;
void *key;
struct log_client *client;
i_error("close(log connection fd) failed: %m");
}
void log_connections_init(void)
{
}
void log_connections_deinit(void)
{
/* normally we don't exit until all log connections are gone,
but we could get here when we're being killed by a signal */
while (log_connections != NULL)
}