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:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user