Make elog() switch to ErrorContext while invoking libpq output routines,
authorTom Lane
Fri, 1 Dec 2000 19:52:04 +0000 (19:52 +0000)
committerTom Lane
Fri, 1 Dec 2000 19:52:04 +0000 (19:52 +0000)
since those routines may do palloc's.  We want to be fairly sure we can
send the error message to the client even under low-memory conditions.
That's what we stashed away 8K in ErrorContext for, after all ...

src/backend/utils/error/elog.c

index fcd8613a7dcba0ddaf4e1a372b266d958f519b7d..e6c19b246ef96cbcca7986fbaa18e221681299ed 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.69 2000/11/25 19:09:22 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.70 2000/12/01 19:52:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include 
 #endif
 
+#include "commands/copy.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "storage/proc.h"
 #include "tcop/tcopprot.h"
-#include "commands/copy.h"
+#include "utils/memutils.h"
 
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
@@ -374,8 +375,17 @@ elog(int lev, const char *fmt, ...)
    if (lev > DEBUG && whereToSendOutput == Remote)
    {
        /* Send IPC message to the front-end program */
+       MemoryContext oldcxt;
        char        msgtype;
 
+       /*
+        * Since backend libpq may call palloc(), switch to a context where
+        * there's fairly likely to be some free space.  After all the
+        * pushups above, we don't want to drop the ball by running out of
+        * space now...
+        */
+       oldcxt = MemoryContextSwitchTo(ErrorContext);
+
        if (lev == NOTICE)
            msgtype = 'N';
        else
@@ -402,6 +412,8 @@ elog(int lev, const char *fmt, ...)
         * much ...
         */
        pq_flush();
+
+       MemoryContextSwitchTo(oldcxt);
    }
 
    if (lev > DEBUG && whereToSendOutput != Remote)
@@ -612,6 +624,7 @@ write_syslog(int level, const char *line)
    static bool openlog_done = false;
    static unsigned long seq = 0;
    static int  syslog_fac = LOG_LOCAL0;
+
    int len = strlen(line);
 
    if (Use_syslog == 0)
@@ -649,19 +662,21 @@ write_syslog(int level, const char *line)
    /* or if the message contains embedded NewLine(s) '\n' */
    if (len > PG_SYSLOG_LIMIT || strchr(line,'\n') != NULL )
    {
-       static char buf[PG_SYSLOG_LIMIT+1];
-       int chunk_nr = 0;
-       int buflen;
+       int     chunk_nr = 0;
 
        while (len > 0)
        {
-           int l;
-           int i;
+           char    buf[PG_SYSLOG_LIMIT+1];
+           int     buflen;
+           int     l;
+           int     i;
+
            /* if we start at a newline, move ahead one char */
            if (line[0] == '\n')
            {
                line++;
                len--;
+               continue;
            }
 
            strncpy(buf, line, PG_SYSLOG_LIMIT);
@@ -681,9 +696,9 @@ write_syslog(int level, const char *line)
                buflen = l;
            else
            {
-               /* try to divide in word boundary */
+               /* try to divide at word boundary */
                i = l - 1;
-               while(i > 0 && !isspace(buf[i]))
+               while (i > 0 && !isspace(buf[i]))
                    i--;
 
                if (i <= 0) /* couldn't divide word boundary */
@@ -702,9 +717,11 @@ write_syslog(int level, const char *line)
            len -= buflen;
        }
    }
-   /* message short enough */
    else
+   {
+       /* message short enough */
        syslog(level, "[%lu] %s", seq, line);
+   }
 }
 
 #endif /* ENABLE_SYSLOG */