]> granicus.if.org Git - postgresql/blob - src/backend/utils/error/elog.c
da8d80763a72f0426ba01120a45f124fdeef91c8
[postgresql] / src / backend / utils / error / elog.c
1 /*-------------------------------------------------------------------------
2  *
3  * elog.c
4  *        error logger
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.61 2000/06/28 03:32:27 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
18 #include <time.h>
19 #include <fcntl.h>
20 #ifndef O_RDONLY
21 #include <sys/file.h>
22 #endif   /* O_RDONLY */
23 #include <sys/types.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <signal.h>
27 #include <sys/time.h>
28 #include <ctype.h>
29 #ifdef ENABLE_SYSLOG
30 #include <syslog.h>
31 #endif
32
33 #include "libpq/libpq.h"
34 #include "libpq/pqformat.h"
35 #include "miscadmin.h"
36 #include "storage/proc.h"
37 #include "tcop/tcopprot.h"
38 #include "commands/copy.h"
39
40 extern int      errno;
41 extern int      sys_nerr;
42
43 extern CommandDest whereToSendOutput;
44
45 #ifdef ENABLE_SYSLOG
46 /*
47  * 0 = only stdout/stderr
48  * 1 = stdout+stderr and syslog
49  * 2 = syslog only
50  * ... in theory anyway
51  */
52 int Use_syslog = 0;
53
54 static void write_syslog(int level, const char *line);
55
56 #else
57 # define Use_syslog 0
58 #endif
59
60 bool Log_timestamp;
61 bool Log_pid;
62
63 #define TIMESTAMP_SIZE 20               /* format `YYYY-MM-DD HH:MM:SS ' */
64 #define PID_SIZE 9                              /* format `[123456] ' */
65
66 static const char * print_timestamp(void);
67 static const char * print_pid(void);
68
69 static int      Debugfile = -1;
70 static int      Err_file = -1;
71 static int      ElogDebugIndentLevel = 0;
72
73 /*--------------------
74  * elog
75  *              Primary error logging function.
76  *
77  * 'lev': error level; indicates recovery action to take, if any.
78  * 'fmt': a printf-style string.
79  * Additional arguments, if any, are formatted per %-escapes in 'fmt'.
80  *
81  * In addition to the usual %-escapes recognized by printf, "%m" in
82  * fmt is replaced by the error message for the current value of errno.
83  *
84  * Note: no newline is needed at the end of the fmt string, since
85  * elog will provide one for the output methods that need it.
86  *
87  * If 'lev' is ERROR or worse, control does not return to the caller.
88  * See elog.h for the error level definitions.
89  *--------------------
90  */
91 void
92 elog(int lev, const char *fmt, ...)
93 {
94         va_list         ap;
95         /*
96          * The expanded format and final output message are dynamically
97          * allocated if necessary, but not if they fit in the "reasonable
98          * size" buffers shown here.  In extremis, we'd rather depend on
99          * having a few hundred bytes of stack space than on malloc() still
100          * working (since memory-clobber errors often take out malloc first).
101          * Don't make these buffers unreasonably large though, on pain of
102          * having to chase a bug with no error message.
103          *
104          * Note that we use malloc() not palloc() because we want to retain
105          * control if we run out of memory.  palloc() would recursively call
106          * elog(ERROR), which would be all right except if we are working on a
107          * FATAL or REALLYFATAL error.  We'd lose track of the fatal condition
108          * and report a mere ERROR to outer loop, which would be a Bad Thing.
109          * So, we substitute an appropriate message in-place, without downgrading
110          * the level if it's above ERROR.
111          */
112         char            fmt_fixedbuf[128];
113         char            msg_fixedbuf[256];
114         char       *fmt_buf = fmt_fixedbuf;
115         char       *msg_buf = msg_fixedbuf;
116         /* this buffer is only used for strange values of lev: */
117         char            prefix_buf[32];
118         /* this buffer is only used if errno has a bogus value: */
119         char            errorstr_buf[32];
120         const char *errorstr;
121         const char *prefix;
122         const char *cp;
123         char       *bp;
124         int                     indent = 0;
125         int                     space_needed;
126         int                     len;
127         /* size of the prefix needed for timestamp and pid, if enabled */
128         size_t      timestamp_size;
129
130         if (lev <= DEBUG && Debugfile < 0)
131                 return;                                 /* ignore debug msgs if noplace to send */
132
133         /* save errno string for %m */
134         if (errno < sys_nerr && errno >= 0)
135                 errorstr = strerror(errno);
136         else
137         {
138                 sprintf(errorstr_buf, "error %d", errno);
139                 errorstr = errorstr_buf;
140         }
141
142         if (lev == ERROR || lev == FATAL)
143         {
144                 /* this is probably redundant... */
145                 if (IsInitProcessingMode())
146                         lev = FATAL;
147         }
148
149         /* choose message prefix and indent level */
150         switch (lev)
151         {
152                 case NOIND:
153                         indent = ElogDebugIndentLevel - 1;
154                         if (indent < 0)
155                                 indent = 0;
156                         if (indent > 30)
157                                 indent = indent % 30;
158                         prefix = "DEBUG:  ";
159                         break;
160                 case DEBUG:
161                         indent = ElogDebugIndentLevel;
162                         if (indent < 0)
163                                 indent = 0;
164                         if (indent > 30)
165                                 indent = indent % 30;
166                         prefix = "DEBUG:  ";
167                         break;
168                 case NOTICE:
169                         prefix = "NOTICE:  ";
170                         break;
171                 case ERROR:
172                         prefix = "ERROR:  ";
173                         break;
174                 default:
175                         sprintf(prefix_buf, "FATAL %d:  ", lev);
176                         prefix = prefix_buf;
177                         break;
178         }
179
180         timestamp_size = 0;
181         if (Log_timestamp)
182                 timestamp_size += TIMESTAMP_SIZE;
183         if (Log_pid)
184                 timestamp_size += PID_SIZE;
185
186         /*
187          * Set up the expanded format, consisting of the prefix string plus
188          * input format, with any %m replaced by strerror() string (since
189          * vsnprintf won't know what to do with %m).  To keep space
190          * calculation simple, we only allow one %m.
191          */
192         space_needed = timestamp_size + strlen(prefix) + indent + (lineno ? 24 : 0)
193                 + strlen(fmt) + strlen(errorstr) + 1;
194         if (space_needed > (int) sizeof(fmt_fixedbuf))
195         {
196                 fmt_buf = (char *) malloc(space_needed);
197                 if (fmt_buf == NULL)
198                 {
199                         /* We're up against it, convert to out-of-memory error */
200                         fmt_buf = fmt_fixedbuf;
201                         if (lev < FATAL)
202                         {
203                                 lev = ERROR;
204                                 prefix = "ERROR:  ";
205                         }
206                         fmt = "elog: out of memory";            /* this must fit in
207                                                                                                  * fmt_fixedbuf! */
208                 }
209         }
210
211         fmt_buf[0] = '\0';
212
213         if (Log_timestamp)
214                 strcat(fmt_buf, print_timestamp());
215         if (Log_pid)
216                 strcat(fmt_buf, print_pid());
217
218         strcat(fmt_buf, prefix);
219
220         bp = fmt_buf + strlen(fmt_buf);
221         while (indent-- > 0)
222                 *bp++ = ' ';
223
224         /* If error was in CopyFrom() print the offending line number -- dz */
225         if (lineno)
226         {
227                 sprintf(bp, "copy: line %d, ", lineno);
228                 bp += strlen(bp);
229                 if (lev == ERROR || lev >= FATAL)
230                         lineno = 0;
231         }
232
233         for (cp = fmt; *cp; cp++)
234         {
235                 if (cp[0] == '%' && cp[1] != '\0')
236                 {
237                         if (cp[1] == 'm')
238                         {
239
240                                 /*
241                                  * XXX If there are any %'s in errorstr then vsnprintf
242                                  * will do the Wrong Thing; do we need to cope? Seems
243                                  * unlikely that % would appear in system errors.
244                                  */
245                                 strcpy(bp, errorstr);
246
247                                 /*
248                                  * copy the rest of fmt literally, since we can't afford
249                                  * to insert another %m.
250                                  */
251                                 strcat(bp, cp + 2);
252                                 bp += strlen(bp);
253                                 break;
254                         }
255                         else
256                         {
257                                 /* copy % and next char --- this avoids trouble with %%m */
258                                 *bp++ = *cp++;
259                                 *bp++ = *cp;
260                         }
261                 }
262                 else
263                         *bp++ = *cp;
264         }
265         *bp = '\0';
266
267         /*
268          * Now generate the actual output text using vsnprintf(). Be sure to
269          * leave space for \n added later as well as trailing null.
270          */
271         space_needed = sizeof(msg_fixedbuf);
272         for (;;)
273         {
274                 int                     nprinted;
275
276                 va_start(ap, fmt);
277                 nprinted = vsnprintf(msg_buf, space_needed - 2, fmt_buf, ap);
278                 va_end(ap);
279
280                 /*
281                  * Note: some versions of vsnprintf return the number of chars
282                  * actually stored, but at least one returns -1 on failure. Be
283                  * conservative about believing whether the print worked.
284                  */
285                 if (nprinted >= 0 && nprinted < space_needed - 3)
286                         break;
287                 /* It didn't work, try to get a bigger buffer */
288                 if (msg_buf != msg_fixedbuf)
289                         free(msg_buf);
290                 space_needed *= 2;
291                 msg_buf = (char *) malloc(space_needed);
292                 if (msg_buf == NULL)
293                 {
294                         /* We're up against it, convert to out-of-memory error */
295                         msg_buf = msg_fixedbuf;
296                         if (lev < FATAL)
297                         {
298                                 lev = ERROR;
299                                 prefix = "ERROR:  ";
300                         }
301                         msg_buf[0] = '\0';
302                         if (Log_timestamp)
303                                 strcat(msg_buf, print_timestamp());
304                         if (Log_pid)
305                                 strcat(msg_buf, print_pid());
306                         strcat(msg_buf, prefix);
307                         strcat(msg_buf, "elog: out of memory");
308                         break;
309                 }
310         }
311
312         /*
313          * Message prepared; send it where it should go
314          */
315
316 #ifdef ENABLE_SYSLOG
317         if (Use_syslog >= 1)
318         {
319                 int syslog_level;
320
321                 switch (lev)
322                 {
323                         case NOIND:
324                                 syslog_level = LOG_DEBUG;
325                                 break;
326                         case DEBUG:
327                                 syslog_level = LOG_DEBUG;
328                                 break;
329                         case NOTICE:
330                                 syslog_level = LOG_NOTICE;
331                                 break;
332                         case ERROR:
333                                 syslog_level = LOG_WARNING;
334                                 break;
335                         case FATAL:
336                                 syslog_level = LOG_ERR;
337                                 break;
338                         case REALLYFATAL:
339                         default:
340                                 syslog_level = LOG_CRIT;
341                 }
342
343                 write_syslog(syslog_level, msg_buf + timestamp_size);
344         }
345 #endif /* ENABLE_SYSLOG */
346
347         /* syslog doesn't want a trailing newline, but other destinations do */
348         strcat(msg_buf, "\n");
349
350         len = strlen(msg_buf);
351
352         if (Debugfile >= 0 && Use_syslog <= 1)
353                 write(Debugfile, msg_buf, len);
354
355         /*
356          * If there's an error log file other than our channel to the
357          * front-end program, write to it first.  This is important because
358          * there's a bug in the socket code on ultrix.  If the front end has
359          * gone away (so the channel to it has been closed at the other end),
360          * then writing here can cause this backend to exit without warning
361          * that is, write() does an exit(). In this case, our only hope of
362          * finding out what's going on is if Err_file was set to some disk
363          * log.  This is a major pain.  (It's probably also long-dead code...
364          * does anyone still use ultrix?)
365          */
366         if (lev > DEBUG && Err_file >= 0 &&
367                 Debugfile != Err_file && Use_syslog <= 1)
368         {
369                 if (write(Err_file, msg_buf, len) < 0)
370                 {
371                         write(open("/dev/console", O_WRONLY, 0666), msg_buf, len);
372                         lev = REALLYFATAL;
373                 }
374                 fsync(Err_file);
375         }
376
377 #ifndef PG_STANDALONE
378
379         if (lev > DEBUG && whereToSendOutput == Remote)
380         {
381                 /* Send IPC message to the front-end program */
382                 char            msgtype;
383
384                 if (lev == NOTICE)
385                         msgtype = 'N';
386                 else
387                 {
388
389                         /*
390                          * Abort any COPY OUT in progress when an error is detected.
391                          * This hack is necessary because of poor design of copy
392                          * protocol.
393                          */
394                         pq_endcopyout(true);
395                         msgtype = 'E';
396                 }
397                 /* exclude the timestamp from msg sent to frontend */
398                 pq_puttextmessage(msgtype, msg_buf + timestamp_size);
399
400                 /*
401                  * This flush is normally not necessary, since postgres.c will
402                  * flush out waiting data when control returns to the main loop.
403                  * But it seems best to leave it here, so that the client has some
404                  * clue what happened if the backend dies before getting back to
405                  * the main loop ... error/notice messages should not be a
406                  * performance-critical path anyway, so an extra flush won't hurt
407                  * much ...
408                  */
409                 pq_flush();
410         }
411
412         if (lev > DEBUG && whereToSendOutput != Remote)
413         {
414
415                 /*
416                  * We are running as an interactive backend, so just send the
417                  * message to stderr.
418                  */
419                 fputs(msg_buf, stderr);
420         }
421
422 #endif   /* !PG_STANDALONE */
423
424         /* done with the message, release space */
425         if (fmt_buf != fmt_fixedbuf)
426                 free(fmt_buf);
427         if (msg_buf != msg_fixedbuf)
428                 free(msg_buf);
429
430         /*
431          * Perform error recovery action as specified by lev.
432          */
433         if (lev == ERROR || lev == FATAL)
434         {
435
436                 /*
437                  * If we have not yet entered the main backend loop (ie, we are in
438                  * the postmaster or in backend startup), then go directly to
439                  * proc_exit.  The same is true if anyone tries to report an error
440                  * after proc_exit has begun to run.  (It's proc_exit's
441                  * responsibility to see that this doesn't turn into infinite
442                  * recursion!)  But in the latter case, we exit with nonzero exit
443                  * code to indicate that something's pretty wrong.
444                  */
445                 if (proc_exit_inprogress || !Warn_restart_ready)
446                 {
447                         fflush(stdout);
448                         fflush(stderr);
449                         ProcReleaseSpins(NULL);         /* get rid of spinlocks we hold */
450                         ProcReleaseLocks(); /* get rid of real locks we hold */
451                         /* XXX shouldn't proc_exit be doing the above?? */
452                         proc_exit((int) proc_exit_inprogress);
453                 }
454
455                 /*
456                  * Guard against infinite loop from elog() during error recovery.
457                  */
458                 if (InError)
459                         elog(REALLYFATAL, "elog: error during error recovery, giving up!");
460                 InError = true;
461
462                 /*
463                  * Otherwise we can return to the main loop in postgres.c. In the
464                  * FATAL case, postgres.c will call proc_exit, but not till after
465                  * completing a standard transaction-abort sequence.
466                  */
467                 ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
468                 if (lev == FATAL)
469                         ExitAfterAbort = true;
470                 siglongjmp(Warn_restart, 1);
471         }
472
473         if (lev > FATAL)
474         {
475
476                 /*
477                  * Serious crash time. Postmaster will observe nonzero process
478                  * exit status and kill the other backends too.
479                  *
480                  * XXX: what if we are *in* the postmaster?  proc_exit() won't kill
481                  * our children...
482                  */
483                 fflush(stdout);
484                 fflush(stderr);
485                 proc_exit(lev);
486         }
487
488         /* We reach here if lev <= NOTICE.      OK to return to caller. */
489 }
490
491 #ifndef PG_STANDALONE
492
493 int
494 DebugFileOpen(void)
495 {
496         int                     fd,
497                                 istty;
498
499         Err_file = Debugfile = -1;
500         ElogDebugIndentLevel = 0;
501
502         if (OutputFileName[0])
503         {
504                 if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY,
505                                            0666)) < 0)
506                         elog(FATAL, "DebugFileOpen: open of %s: %m",
507                                  OutputFileName);
508                 istty = isatty(fd);
509                 close(fd);
510
511                 /*
512                  * If the file is a tty and we're running under the postmaster,
513                  * try to send stdout there as well (if it isn't a tty then stderr
514                  * will block out stdout, so we may as well let stdout go wherever
515                  * it was going before).
516                  */
517                 if (istty &&
518                         IsUnderPostmaster &&
519                         !freopen(OutputFileName, "a", stdout))
520                         elog(FATAL, "DebugFileOpen: %s reopen as stdout: %m",
521                                  OutputFileName);
522                 if (!freopen(OutputFileName, "a", stderr))
523                         elog(FATAL, "DebugFileOpen: %s reopen as stderr: %m",
524                                  OutputFileName);
525                 Err_file = Debugfile = fileno(stderr);
526                 return Debugfile;
527         }
528
529         /*
530          * If no filename was specified, send debugging output to stderr. If
531          * stderr has been hosed, try to open a file.
532          */
533         fd = fileno(stderr);
534         if (fcntl(fd, F_GETFD, 0) < 0)
535         {
536                 snprintf(OutputFileName, MAXPGPATH, "%s%cpg.errors.%d",
537                                  DataDir, SEP_CHAR, (int) MyProcPid);
538                 fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666);
539         }
540         if (fd < 0)
541                 elog(FATAL, "DebugFileOpen: could not open debugging file");
542
543         Err_file = Debugfile = fd;
544         return Debugfile;
545 }
546
547 #endif
548
549
550
551 /*
552  * Return a timestamp string like
553  *
554  *   "2000-06-04 13:12:03 "
555  */
556 static const char *
557 print_timestamp(void)
558 {
559         time_t curtime;
560         static char buf[TIMESTAMP_SIZE + 1];
561
562         curtime = time(NULL);
563
564         strftime(buf, sizeof(buf),
565                          "%Y-%m-%d %H:%M:%S ",
566                          localtime(&curtime));
567
568         return buf;
569 }
570
571
572
573 /*
574  * Return a string like
575  *
576  *     "[123456] "
577  *
578  * with the current pid.
579  */
580 static const char *
581 print_pid(void)
582 {
583         static char buf[PID_SIZE + 1];
584
585         snprintf(buf, PID_SIZE + 1, "[%d]      ", (int)MyProcPid);
586         return buf;
587 }
588
589
590
591 #ifdef ENABLE_SYSLOG
592
593 /*
594  * Write a message line to syslog if the syslog option is set.
595  *
596  * Our problem here is that many syslog implementations don't handle
597  * long messages in an acceptable manner. While this function doesn't
598  * help that fact, it does work around by splitting up messages into
599  * smaller pieces.
600  */
601 static void
602 write_syslog(int level, const char *line)
603 {
604 #ifndef PG_SYSLOG_LIMIT
605 # define PG_SYSLOG_LIMIT 128
606 #endif
607
608         static bool     openlog_done = false;
609         static unsigned long seq = 0;
610         int len = strlen(line);
611
612         if (Use_syslog == 0)
613                 return;
614
615         if (!openlog_done)
616         {
617                 openlog("postgres", LOG_PID | LOG_NDELAY, LOG_LOCAL0);
618                 openlog_done = true;
619         }
620
621         /*
622          * We add a sequence number to each log message to suppress "same"
623          * messages.
624          */
625         seq++;
626
627         /* divide into multiple syslog() calls if message is too long */
628         if (len > PG_SYSLOG_LIMIT)
629         {
630                 static char     buf[PG_SYSLOG_LIMIT+1];
631                 int chunk_nr = 0;
632                 int buflen;
633
634                 while (len > 0)
635                 {
636                         int l;
637                         int i;
638
639                         strncpy(buf, line, PG_SYSLOG_LIMIT);
640                         buf[PG_SYSLOG_LIMIT] = '\0';
641
642                         l = strlen(buf);
643 #ifdef MULTIBYTE
644                         /* trim to multibyte letter boundary */ 
645                         buflen = pg_mbcliplen(buf, l, l);
646                         buf[buflen] = '\0';
647                         l = strlen(buf);
648 #endif
649                         /* already word boundary? */
650                         if (isspace(line[l]) || line[l] == '\0')
651                                 buflen = l;
652                         else
653                         {
654                                 /* try to divide in word boundary */
655                                 i = l - 1;
656                                 while(i > 0 && !isspace(buf[i]))
657                                         i--;
658
659                                 if (i <= 0)     /* couldn't divide word boundary */
660                                         buflen = l;
661                                 else
662                                 {
663                                         buflen = i;
664                                         buf[i] = '\0';
665                                 }
666                         }
667
668                         chunk_nr++;
669
670                         syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf);
671                         line += buflen;
672                         len -= buflen;
673                 }
674         }
675         /* message short enough */
676         else
677                 syslog(level, "[%lu] %s", seq, line);
678 }
679
680 #endif /* ENABLE_SYSLOG */