aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/error/elog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/error/elog.c')
-rw-r--r--src/backend/utils/error/elog.c111
1 files changed, 93 insertions, 18 deletions
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 06a78f2d701..5f30e783756 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.217 2009/07/03 19:14:25 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.218 2009/10/17 00:24:50 mha Exp $
*
*-------------------------------------------------------------------------
*/
@@ -111,8 +111,10 @@ static int syslog_facility = LOG_LOCAL0;
static void write_syslog(int level, const char *line);
#endif
+static void write_console(const char *line, int len);
+
#ifdef WIN32
-static void write_eventlog(int level, const char *line);
+static void write_eventlog(int level, const char *line, int len);
#endif
/* We provide a small stack of ErrorData records for re-entrant cases */
@@ -1567,10 +1569,11 @@ write_syslog(int level, const char *line)
* Write a message line to the windows event log
*/
static void
-write_eventlog(int level, const char *line)
+write_eventlog(int level, const char *line, int len)
{
- int eventlevel = EVENTLOG_ERROR_TYPE;
- static HANDLE evtHandle = INVALID_HANDLE_VALUE;
+ WCHAR *utf16;
+ int eventlevel = EVENTLOG_ERROR_TYPE;
+ static HANDLE evtHandle = INVALID_HANDLE_VALUE;
if (evtHandle == INVALID_HANDLE_VALUE)
{
@@ -1606,8 +1609,34 @@ write_eventlog(int level, const char *line)
break;
}
-
- ReportEvent(evtHandle,
+ /*
+ * Convert message to UTF16 text and write it with ReportEventW,
+ * but fall-back into ReportEventA if conversion failed.
+ *
+ * Also verify that we are not on our way into error recursion trouble
+ * due to error messages thrown deep inside pgwin32_toUTF16().
+ */
+ if (GetDatabaseEncoding() != GetPlatformEncoding() &&
+ !in_error_recursion_trouble())
+ {
+ utf16 = pgwin32_toUTF16(line, len, NULL);
+ if (utf16)
+ {
+ ReportEventW(evtHandle,
+ eventlevel,
+ 0,
+ 0, /* All events are Id 0 */
+ NULL,
+ 1,
+ 0,
+ (LPCWSTR *) &utf16,
+ NULL);
+
+ pfree(utf16);
+ return;
+ }
+ }
+ ReportEventA(evtHandle,
eventlevel,
0,
0, /* All events are Id 0 */
@@ -1619,6 +1648,52 @@ write_eventlog(int level, const char *line)
}
#endif /* WIN32 */
+static void
+write_console(const char *line, int len)
+{
+#ifdef WIN32
+ /*
+ * WriteConsoleW() will fail of stdout is redirected, so just fall through
+ * to writing unconverted to the logfile in this case.
+ */
+ if (GetDatabaseEncoding() != GetPlatformEncoding() &&
+ !in_error_recursion_trouble() &&
+ !redirection_done)
+ {
+ WCHAR *utf16;
+ int utf16len;
+
+ utf16 = pgwin32_toUTF16(line, len, &utf16len);
+ if (utf16 != NULL)
+ {
+ HANDLE stdHandle;
+ DWORD written;
+
+ stdHandle = GetStdHandle(STD_ERROR_HANDLE);
+ if (WriteConsoleW(stdHandle, utf16, utf16len, &written, NULL))
+ {
+ pfree(utf16);
+ return;
+ }
+
+ /*
+ * In case WriteConsoleW() failed, fall back to writing the message
+ * unconverted.
+ */
+ pfree(utf16);
+ }
+ }
+#else
+ /*
+ * Conversion on non-win32 platform is not implemented yet.
+ * It requires non-throw version of pg_do_encoding_conversion(),
+ * that converts unconvertable characters to '?' without errors.
+ */
+#endif
+
+ write(fileno(stderr), line, len);
+}
+
/*
* setup formatted_log_time, for consistent times between CSV and regular logs
*/
@@ -2206,7 +2281,7 @@ send_message_to_server_log(ErrorData *edata)
/* Write to eventlog, if enabled */
if (Log_destination & LOG_DESTINATION_EVENTLOG)
{
- write_eventlog(edata->elevel, buf.data);
+ write_eventlog(edata->elevel, buf.data, buf.len);
}
#endif /* WIN32 */
@@ -2230,10 +2305,10 @@ send_message_to_server_log(ErrorData *edata)
* because that's really a pipe to the syslogger process.
*/
else if (pgwin32_is_service())
- write_eventlog(edata->elevel, buf.data);
+ write_eventlog(edata->elevel, buf.data, buf.len);
#endif
else
- write(fileno(stderr), buf.data, buf.len);
+ write_console(buf.data, buf.len);
}
/* If in the syslogger process, try to write messages direct to file */
@@ -2256,12 +2331,12 @@ send_message_to_server_log(ErrorData *edata)
{
const char *msg = _("Not safe to send CSV data\n");
- write(fileno(stderr), msg, strlen(msg));
+ write_console(msg, strlen(msg));
if (!(Log_destination & LOG_DESTINATION_STDERR) &&
whereToSendOutput != DestDebug)
{
/* write message to stderr unless we just sent it above */
- write(fileno(stderr), buf.data, buf.len);
+ write_console(buf.data, buf.len);
}
pfree(buf.data);
}
@@ -2642,6 +2717,9 @@ void
write_stderr(const char *fmt,...)
{
va_list ap;
+#ifdef WIN32
+ char errbuf[2048]; /* Arbitrary size? */
+#endif
fmt = _(fmt);
@@ -2651,6 +2729,7 @@ write_stderr(const char *fmt,...)
vfprintf(stderr, fmt, ap);
fflush(stderr);
#else
+ vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
/*
* On Win32, we print to stderr if running on a console, or write to
@@ -2658,16 +2737,12 @@ write_stderr(const char *fmt,...)
*/
if (pgwin32_is_service()) /* Running as a service */
{
- char errbuf[2048]; /* Arbitrary size? */
-
- vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
-
- write_eventlog(ERROR, errbuf);
+ write_eventlog(ERROR, errbuf, strlen(errbuf));
}
else
{
/* Not running as service, write to stderr */
- vfprintf(stderr, fmt, ap);
+ write_console(errbuf, strlen(errbuf));
fflush(stderr);
}
#endif