aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/error/elog.c
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2007-06-14 01:49:39 +0000
committerAndrew Dunstan <andrew@dunslane.net>2007-06-14 01:49:39 +0000
commit0998720d0cf4bf6197d2d8d4caef77dbe03a0e18 (patch)
tree6fd921c58463e8009656962e88973b865ef17606 /src/backend/utils/error/elog.c
parent83d95b572b8ef344b74da2ceb1fdfa8579a20638 (diff)
downloadpostgresql-0998720d0cf4bf6197d2d8d4caef77dbe03a0e18.tar.gz
postgresql-0998720d0cf4bf6197d2d8d4caef77dbe03a0e18.zip
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
Diffstat (limited to 'src/backend/utils/error/elog.c')
-rw-r--r--src/backend/utils/error/elog.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 18717e79e83..49771ae349a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -42,7 +42,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.178.2.1 2007/02/11 15:12:21 mha Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.178.2.2 2007/06/14 01:49:39 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@@ -123,7 +123,7 @@ static char *expand_fmt_string(const char *fmt, ErrorData *edata);
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 void write_pipe_chunks(int fd, char *data, int len);
/*
* errstart --- begin an error-reporting cycle
@@ -1724,7 +1724,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 */
@@ -1734,6 +1737,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
@@ -2056,6 +2090,7 @@ write_stderr(const char *fmt,...)
#ifndef WIN32
/* On Unix, we just fprintf to stderr */
vfprintf(stderr, fmt, ap);
+ fflush(stderr);
#else
/*
@@ -2071,8 +2106,11 @@ write_stderr(const char *fmt,...)
write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
}
else
+ {
/* Not running as service, write to stderr */
vfprintf(stderr, fmt, ap);
+ fflush(stderr);
+ }
#endif
va_end(ap);
}