1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Implement a chunking protocol for writes to the syslogger pipe, with messages

reassembled in the syslogger before writing to the log file. This prevents
partial messages from being written, which mucks up log rotation, and
messages from different backends being interleaved, which causes garbled
logs. Backport as far as 8.0, where the syslogger was introduced.

Tom Lane and Andrew Dunstan
This commit is contained in:
Andrew Dunstan
2007-06-14 01:48:51 +00:00
parent 320f820585
commit bd2cb9aaa5
3 changed files with 345 additions and 16 deletions

View File

@ -42,7 +42,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.186 2007/06/07 21:45:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.187 2007/06/14 01:48:51 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@ -124,6 +124,7 @@ static const char *useful_strerror(int errnum);
static const char *error_severity(int elevel);
static void append_with_tabs(StringInfo buf, const char *str);
static bool is_log_level_output(int elevel, int log_min_level);
static void write_pipe_chunks(int fd, char *data, int len);
/*
@ -1783,7 +1784,10 @@ send_message_to_server_log(ErrorData *edata)
write_eventlog(edata->elevel, buf.data);
else
#endif
fprintf(stderr, "%s", buf.data);
if (Redirect_stderr)
write_pipe_chunks(fileno(stderr), buf.data, buf.len);
else
write(fileno(stderr), buf.data, buf.len);
}
/* If in the syslogger process, try to write messages direct to file */
@ -1793,6 +1797,37 @@ send_message_to_server_log(ErrorData *edata)
pfree(buf.data);
}
/*
* Send data to the syslogger using the chunked protocol
*/
static void
write_pipe_chunks(int fd, char *data, int len)
{
PipeProtoChunk p;
Assert(len > 0);
p.proto.nuls[0] = p.proto.nuls[1] = '\0';
p.proto.pid = MyProcPid;
/* write all but the last chunk */
while (len > PIPE_MAX_PAYLOAD)
{
p.proto.is_last = 'f';
p.proto.len = PIPE_MAX_PAYLOAD;
memcpy(p.proto.data, data, PIPE_MAX_PAYLOAD);
write(fd, &p, PIPE_HEADER_SIZE + PIPE_MAX_PAYLOAD);
data += PIPE_MAX_PAYLOAD;
len -= PIPE_MAX_PAYLOAD;
}
/* write the last chunk */
p.proto.is_last = 't';
p.proto.len = len;
memcpy(p.proto.data, data, len);
write(fd, &p, PIPE_HEADER_SIZE + len);
}
/*
* Write error report to client
@ -2115,6 +2150,7 @@ write_stderr(const char *fmt,...)
#ifndef WIN32
/* On Unix, we just fprintf to stderr */
vfprintf(stderr, fmt, ap);
fflush(stderr);
#else
/*
@ -2130,8 +2166,11 @@ write_stderr(const char *fmt,...)
write_eventlog(ERROR, errbuf);
}
else
{
/* Not running as service, write to stderr */
vfprintf(stderr, fmt, ap);
fflush(stderr);
}
#endif
va_end(ap);
}