Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * elog.c
4 : : * error logging and reporting
5 : : *
6 : : * Because of the extremely high rate at which log messages can be generated,
7 : : * we need to be mindful of the performance cost of obtaining any information
8 : : * that may be logged. Also, it's important to keep in mind that this code may
9 : : * get called from within an aborted transaction, in which case operations
10 : : * such as syscache lookups are unsafe.
11 : : *
12 : : * Some notes about recursion and errors during error processing:
13 : : *
14 : : * We need to be robust about recursive-error scenarios --- for example,
15 : : * if we run out of memory, it's important to be able to report that fact.
16 : : * There are a number of considerations that go into this.
17 : : *
18 : : * First, distinguish between re-entrant use and actual recursion. It
19 : : * is possible for an error or warning message to be emitted while the
20 : : * parameters for an error message are being computed. In this case
21 : : * errstart has been called for the outer message, and some field values
22 : : * may have already been saved, but we are not actually recursing. We handle
23 : : * this by providing a (small) stack of ErrorData records. The inner message
24 : : * can be computed and sent without disturbing the state of the outer message.
25 : : * (If the inner message is actually an error, this isn't very interesting
26 : : * because control won't come back to the outer message generator ... but
27 : : * if the inner message is only debug or log data, this is critical.)
28 : : *
29 : : * Second, actual recursion will occur if an error is reported by one of
30 : : * the elog.c routines or something they call. By far the most probable
31 : : * scenario of this sort is "out of memory"; and it's also the nastiest
32 : : * to handle because we'd likely also run out of memory while trying to
33 : : * report this error! Our escape hatch for this case is to reset the
34 : : * ErrorContext to empty before trying to process the inner error. Since
35 : : * ErrorContext is guaranteed to have at least 8K of space in it (see mcxt.c),
36 : : * we should be able to process an "out of memory" message successfully.
37 : : * Since we lose the prior error state due to the reset, we won't be able
38 : : * to return to processing the original error, but we wouldn't have anyway.
39 : : * (NOTE: the escape hatch is not used for recursive situations where the
40 : : * inner message is of less than ERROR severity; in that case we just
41 : : * try to process it and return normally. Usually this will work, but if
42 : : * it ends up in infinite recursion, we will PANIC due to error stack
43 : : * overflow.)
44 : : *
45 : : *
46 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
47 : : * Portions Copyright (c) 1994, Regents of the University of California
48 : : *
49 : : *
50 : : * IDENTIFICATION
51 : : * src/backend/utils/error/elog.c
52 : : *
53 : : *-------------------------------------------------------------------------
54 : : */
55 : : #include "postgres.h"
56 : :
57 : : #include <fcntl.h>
58 : : #include <time.h>
59 : : #include <unistd.h>
60 : : #include <signal.h>
61 : : #include <ctype.h>
62 : : #ifdef HAVE_SYSLOG
63 : : #include <syslog.h>
64 : : #endif
65 : : #ifdef HAVE_EXECINFO_H
66 : : #include <execinfo.h>
67 : : #endif
68 : :
69 : : #include "access/xact.h"
70 : : #include "libpq/libpq.h"
71 : : #include "libpq/pqformat.h"
72 : : #include "mb/pg_wchar.h"
73 : : #include "miscadmin.h"
74 : : #include "nodes/miscnodes.h"
75 : : #include "pgstat.h"
76 : : #include "postmaster/bgworker.h"
77 : : #include "postmaster/postmaster.h"
78 : : #include "postmaster/syslogger.h"
79 : : #include "storage/ipc.h"
80 : : #include "storage/proc.h"
81 : : #include "tcop/tcopprot.h"
82 : : #include "utils/guc_hooks.h"
83 : : #include "utils/memutils.h"
84 : : #include "utils/ps_status.h"
85 : : #include "utils/varlena.h"
86 : :
87 : :
88 : : /* In this module, access gettext() via err_gettext() */
89 : : #undef _
90 : : #define _(x) err_gettext(x)
91 : :
92 : :
93 : : /* Global variables */
94 : : ErrorContextCallback *error_context_stack = NULL;
95 : :
96 : : sigjmp_buf *PG_exception_stack = NULL;
97 : :
98 : : extern bool redirection_done;
99 : :
100 : : /*
101 : : * Hook for intercepting messages before they are sent to the server log.
102 : : * Note that the hook will not get called for messages that are suppressed
103 : : * by log_min_messages. Also note that logging hooks implemented in preload
104 : : * libraries will miss any log messages that are generated before the
105 : : * library is loaded.
106 : : */
107 : : emit_log_hook_type emit_log_hook = NULL;
108 : :
109 : : /* GUC parameters */
110 : : int Log_error_verbosity = PGERROR_DEFAULT;
111 : : char *Log_line_prefix = NULL; /* format for extra log line info */
112 : : int Log_destination = LOG_DESTINATION_STDERR;
113 : : char *Log_destination_string = NULL;
114 : : bool syslog_sequence_numbers = true;
115 : : bool syslog_split_messages = true;
116 : :
117 : : /* Processed form of backtrace_functions GUC */
118 : : static char *backtrace_function_list;
119 : :
120 : : #ifdef HAVE_SYSLOG
121 : :
122 : : /*
123 : : * Max string length to send to syslog(). Note that this doesn't count the
124 : : * sequence-number prefix we add, and of course it doesn't count the prefix
125 : : * added by syslog itself. Solaris and sysklogd truncate the final message
126 : : * at 1024 bytes, so this value leaves 124 bytes for those prefixes. (Most
127 : : * other syslog implementations seem to have limits of 2KB or so.)
128 : : */
129 : : #ifndef PG_SYSLOG_LIMIT
130 : : #define PG_SYSLOG_LIMIT 900
131 : : #endif
132 : :
133 : : static bool openlog_done = false;
134 : : static char *syslog_ident = NULL;
135 : : static int syslog_facility = LOG_LOCAL0;
136 : :
137 : : static void write_syslog(int level, const char *line);
138 : : #endif
139 : :
140 : : #ifdef WIN32
141 : : extern char *event_source;
142 : :
143 : : static void write_eventlog(int level, const char *line, int len);
144 : : #endif
145 : :
146 : : /* We provide a small stack of ErrorData records for re-entrant cases */
147 : : #define ERRORDATA_STACK_SIZE 5
148 : :
149 : : static ErrorData errordata[ERRORDATA_STACK_SIZE];
150 : :
151 : : static int errordata_stack_depth = -1; /* index of topmost active frame */
152 : :
153 : : static int recursion_depth = 0; /* to detect actual recursion */
154 : :
155 : : /*
156 : : * Saved timeval and buffers for formatted timestamps that might be used by
157 : : * log_line_prefix, csv logs and JSON logs.
158 : : */
159 : : static struct timeval saved_timeval;
160 : : static bool saved_timeval_set = false;
161 : :
162 : : #define FORMATTED_TS_LEN 128
163 : : static char formatted_start_time[FORMATTED_TS_LEN];
164 : : static char formatted_log_time[FORMATTED_TS_LEN];
165 : :
166 : :
167 : : /* Macro for checking errordata_stack_depth is reasonable */
168 : : #define CHECK_STACK_DEPTH() \
169 : : do { \
170 : : if (errordata_stack_depth < 0) \
171 : : { \
172 : : errordata_stack_depth = -1; \
173 : : ereport(ERROR, (errmsg_internal("errstart was not called"))); \
174 : : } \
175 : : } while (0)
176 : :
177 : :
178 : : static const char *err_gettext(const char *str) pg_attribute_format_arg(1);
179 : : static ErrorData *get_error_stack_entry(void);
180 : : static void set_stack_entry_domain(ErrorData *edata, const char *domain);
181 : : static void set_stack_entry_location(ErrorData *edata,
182 : : const char *filename, int lineno,
183 : : const char *funcname);
184 : : static bool matches_backtrace_functions(const char *funcname);
185 : : static pg_noinline void set_backtrace(ErrorData *edata, int num_skip);
186 : : static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str);
187 : : static void FreeErrorDataContents(ErrorData *edata);
188 : : static void write_console(const char *line, int len);
189 : : static const char *process_log_prefix_padding(const char *p, int *ppadding);
190 : : static void log_line_prefix(StringInfo buf, ErrorData *edata);
191 : : static void send_message_to_server_log(ErrorData *edata);
192 : : static void send_message_to_frontend(ErrorData *edata);
193 : : static void append_with_tabs(StringInfo buf, const char *str);
194 : :
195 : :
196 : : /*
197 : : * is_log_level_output -- is elevel logically >= log_min_level?
198 : : *
199 : : * We use this for tests that should consider LOG to sort out-of-order,
200 : : * between ERROR and FATAL. Generally this is the right thing for testing
201 : : * whether a message should go to the postmaster log, whereas a simple >=
202 : : * test is correct for testing whether the message should go to the client.
203 : : */
204 : : static inline bool
1238 tgl@sss.pgh.pa.us 205 :CBC 19259671 : is_log_level_output(int elevel, int log_min_level)
206 : : {
207 [ + + + + ]: 19259671 : if (elevel == LOG || elevel == LOG_SERVER_ONLY)
208 : : {
209 [ + - + + ]: 540053 : if (log_min_level == LOG || log_min_level <= ERROR)
210 : 540052 : return true;
211 : : }
1202 212 [ + + ]: 18719618 : else if (elevel == WARNING_CLIENT_ONLY)
213 : : {
214 : : /* never sent to log, regardless of log_min_level */
215 : 7 : return false;
216 : : }
1238 217 [ - + ]: 18719611 : else if (log_min_level == LOG)
218 : : {
219 : : /* elevel != LOG */
1238 tgl@sss.pgh.pa.us 220 [ # # ]:UBC 0 : if (elevel >= FATAL)
221 : 0 : return true;
222 : : }
223 : : /* Neither is LOG */
1238 tgl@sss.pgh.pa.us 224 [ + + ]:CBC 18719611 : else if (elevel >= log_min_level)
225 : 193039 : return true;
226 : :
227 : 18526573 : return false;
228 : : }
229 : :
230 : : /*
231 : : * Policy-setting subroutines. These are fairly simple, but it seems wise
232 : : * to have the code in just one place.
233 : : */
234 : :
235 : : /*
236 : : * should_output_to_server --- should message of given elevel go to the log?
237 : : */
238 : : static inline bool
239 : 18821518 : should_output_to_server(int elevel)
240 : : {
241 : 18821518 : return is_log_level_output(elevel, log_min_messages);
242 : : }
243 : :
244 : : /*
245 : : * should_output_to_client --- should message of given elevel go to the client?
246 : : */
247 : : static inline bool
248 : 18820670 : should_output_to_client(int elevel)
249 : : {
250 [ + + + + ]: 18820670 : if (whereToSendOutput == DestRemote && elevel != LOG_SERVER_ONLY)
251 : : {
252 : : /*
253 : : * client_min_messages is honored only after we complete the
254 : : * authentication handshake. This is required both for security
255 : : * reasons and because many clients can't handle NOTICE messages
256 : : * during authentication.
257 : : */
258 [ + + ]: 1502721 : if (ClientAuthInProgress)
259 : 31074 : return (elevel >= ERROR);
260 : : else
261 [ + + + + ]: 1471647 : return (elevel >= client_min_messages || elevel == INFO);
262 : : }
263 : 17317949 : return false;
264 : : }
265 : :
266 : :
267 : : /*
268 : : * message_level_is_interesting --- would ereport/elog do anything?
269 : : *
270 : : * Returns true if ereport/elog with this elevel will not be a no-op.
271 : : * This is useful to short-circuit any expensive preparatory work that
272 : : * might be needed for a logging message. There is no point in
273 : : * prepending this to a bare ereport/elog call, however.
274 : : */
275 : : bool
276 : 1145366 : message_level_is_interesting(int elevel)
277 : : {
278 : : /*
279 : : * Keep this in sync with the decision-making in errstart().
280 : : */
281 [ + - + + ]: 2290732 : if (elevel >= ERROR ||
282 [ + + ]: 2289884 : should_output_to_server(elevel) ||
283 : 1144518 : should_output_to_client(elevel))
284 : 2029 : return true;
285 : 1143337 : return false;
286 : : }
287 : :
288 : :
289 : : /*
290 : : * in_error_recursion_trouble --- are we at risk of infinite error recursion?
291 : : *
292 : : * This function exists to provide common control of various fallback steps
293 : : * that we take if we think we are facing infinite error recursion. See the
294 : : * callers for details.
295 : : */
296 : : bool
5648 297 : 2092993 : in_error_recursion_trouble(void)
298 : : {
299 : : /* Pull the plug if recurse more than once */
300 : 2092993 : return (recursion_depth > 2);
301 : : }
302 : :
303 : : /*
304 : : * One of those fallback steps is to stop trying to localize the error
305 : : * message, since there's a significant probability that that's exactly
306 : : * what's causing the recursion.
307 : : */
308 : : static inline const char *
5522 309 : 752552 : err_gettext(const char *str)
310 : : {
311 : : #ifdef ENABLE_NLS
312 [ + + ]: 752552 : if (in_error_recursion_trouble())
313 : 2 : return str;
314 : : else
315 : 752550 : return gettext(str);
316 : : #else
317 : : return str;
318 : : #endif
319 : : }
320 : :
321 : : /*
322 : : * errstart_cold
323 : : * A simple wrapper around errstart, but hinted to be "cold". Supporting
324 : : * compilers are more likely to move code for branches containing this
325 : : * function into an area away from the calling function's code. This can
326 : : * result in more commonly executed code being more compact and fitting
327 : : * on fewer cache lines.
328 : : */
329 : : pg_attribute_cold bool
1237 drowley@postgresql.o 330 : 19960 : errstart_cold(int elevel, const char *domain)
331 : : {
332 : 19960 : return errstart(elevel, domain);
333 : : }
334 : :
335 : : /*
336 : : * errstart --- begin an error-reporting cycle
337 : : *
338 : : * Create and initialize error stack entry. Subsequently, errmsg() and
339 : : * perhaps other routines will be called to further populate the stack entry.
340 : : * Finally, errfinish() will be called to actually process the error report.
341 : : *
342 : : * Returns true in normal case. Returns false to short-circuit the error
343 : : * report (if it's a warning or lower and not to be reported anywhere).
344 : : */
345 : : bool
1482 tgl@sss.pgh.pa.us 346 : 17676152 : errstart(int elevel, const char *domain)
347 : : {
348 : : ErrorData *edata;
349 : : bool output_to_server;
8079 bruce@momjian.us 350 : 17676152 : bool output_to_client = false;
351 : : int i;
352 : :
353 : : /*
354 : : * Check some cases in which we want to promote an error into a more
355 : : * severe error. None of this logic applies for non-error messages.
356 : : */
7661 tgl@sss.pgh.pa.us 357 [ + + ]: 17676152 : if (elevel >= ERROR)
358 : : {
359 : : /*
360 : : * If we are inside a critical section, all errors become PANIC
361 : : * errors. See miscadmin.h.
362 : : */
8486 363 [ - + ]: 24082 : if (CritSectionCount > 0)
7661 tgl@sss.pgh.pa.us 364 :UBC 0 : elevel = PANIC;
365 : :
366 : : /*
367 : : * Check reasons for treating ERROR as FATAL:
368 : : *
369 : : * 1. we have no handler to pass the error to (implies we are in the
370 : : * postmaster or in backend startup).
371 : : *
372 : : * 2. ExitOnAnyError mode switch is set (initdb uses this).
373 : : *
374 : : * 3. the error occurred after proc_exit has begun to run. (It's
375 : : * proc_exit's responsibility to see that this doesn't turn into
376 : : * infinite recursion!)
377 : : */
7161 tgl@sss.pgh.pa.us 378 [ + + ]:CBC 24082 : if (elevel == ERROR)
379 : : {
380 [ + + + - ]: 23551 : if (PG_exception_stack == NULL ||
381 [ - + ]: 23290 : ExitOnAnyError ||
382 : : proc_exit_inprogress)
383 : 261 : elevel = FATAL;
384 : : }
385 : :
386 : : /*
387 : : * If the error level is ERROR or more, errfinish is not going to
388 : : * return to caller; therefore, if there is any stacked error already
389 : : * in progress it will be lost. This is more or less okay, except we
390 : : * do not want to have a FATAL or PANIC error downgraded because the
391 : : * reporting process was interrupted by a lower-grade error. So check
392 : : * the stack and make sure we panic if panic is warranted.
393 : : */
394 [ + + ]: 24083 : for (i = 0; i <= errordata_stack_depth; i++)
395 : 1 : elevel = Max(elevel, errordata[i].elevel);
396 : : }
397 : :
398 : : /*
399 : : * Now decide whether we need to process this report at all; if it's
400 : : * warning or less and not enabled for logging, just return false without
401 : : * starting up any error logging machinery.
402 : : */
1238 403 : 17676152 : output_to_server = should_output_to_server(elevel);
404 : 17676152 : output_to_client = should_output_to_client(elevel);
7661 405 [ + + + + : 17676152 : if (elevel < ERROR && !output_to_server && !output_to_client)
+ + ]
406 : 17223627 : return false;
407 : :
408 : : /*
409 : : * We need to do some actual work. Make sure that memory context
410 : : * initialization has finished, else we can't do anything useful.
411 : : */
3746 412 [ - + ]: 452525 : if (ErrorContext == NULL)
413 : : {
414 : : /* Oops, hard crash time; very little we can do safely here */
1482 tgl@sss.pgh.pa.us 415 :UBC 0 : write_stderr("error occurred before error message processing is available\n");
3746 416 : 0 : exit(2);
417 : : }
418 : :
419 : : /*
420 : : * Okay, crank up a stack entry to store the info in.
421 : : */
422 : :
7161 tgl@sss.pgh.pa.us 423 [ + + - + ]:CBC 452525 : if (recursion_depth++ > 0 && elevel >= ERROR)
424 : : {
425 : : /*
426 : : * Oops, error during error processing. Clear ErrorContext as
427 : : * discussed at top of file. We will not return to the original
428 : : * error's reporter or handler, so we don't need it.
429 : : */
7661 tgl@sss.pgh.pa.us 430 :UBC 0 : MemoryContextReset(ErrorContext);
431 : :
432 : : /*
433 : : * Infinite error recursion might be due to something broken in a
434 : : * context traceback routine. Abandon them too. We also abandon
435 : : * attempting to print the error statement (which, if long, could
436 : : * itself be the source of the recursive failure).
437 : : */
5648 438 [ # # ]: 0 : if (in_error_recursion_trouble())
439 : : {
7661 440 : 0 : error_context_stack = NULL;
6112 441 : 0 : debug_query_string = NULL;
442 : : }
443 : : }
444 : :
445 : : /* Initialize data for this error frame */
494 tgl@sss.pgh.pa.us 446 :CBC 452525 : edata = get_error_stack_entry();
7661 447 : 452525 : edata->elevel = elevel;
448 : 452525 : edata->output_to_server = output_to_server;
449 : 452525 : edata->output_to_client = output_to_client;
494 450 : 452525 : set_stack_entry_domain(edata, domain);
451 : : /* Select default errcode based on elevel */
7576 452 [ + + ]: 452525 : if (elevel >= ERROR)
453 : 24082 : edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
1202 454 [ + + ]: 428443 : else if (elevel >= WARNING)
7576 455 : 144527 : edata->sqlerrcode = ERRCODE_WARNING;
456 : : else
457 : 283916 : edata->sqlerrcode = ERRCODE_SUCCESSFUL_COMPLETION;
458 : :
459 : : /*
460 : : * Any allocations for this error state level should go into ErrorContext
461 : : */
3909 sfrost@snowman.net 462 : 452525 : edata->assoc_context = ErrorContext;
463 : :
7661 tgl@sss.pgh.pa.us 464 : 452525 : recursion_depth--;
465 : 452525 : return true;
466 : : }
467 : :
468 : : /*
469 : : * errfinish --- end an error-reporting cycle
470 : : *
471 : : * Produce the appropriate error report(s) and pop the error stack.
472 : : *
473 : : * If elevel, as passed to errstart(), is ERROR or worse, control does not
474 : : * return to the caller. See elog.h for the error level definitions.
475 : : */
476 : : void
1482 477 : 452525 : errfinish(const char *filename, int lineno, const char *funcname)
478 : : {
7661 479 : 452525 : ErrorData *edata = &errordata[errordata_stack_depth];
480 : : int elevel;
481 : : MemoryContext oldcontext;
482 : : ErrorContextCallback *econtext;
483 : :
7560 484 : 452525 : recursion_depth++;
7661 485 [ - + - - ]: 452525 : CHECK_STACK_DEPTH();
486 : :
487 : : /* Save the last few bits of error state into the stack entry */
494 488 : 452525 : set_stack_entry_location(edata, filename, lineno, funcname);
489 : :
3786 rhaas@postgresql.org 490 : 452525 : elevel = edata->elevel;
491 : :
492 : : /*
493 : : * Do processing in ErrorContext, which we hope has enough reserved space
494 : : * to report an error.
495 : : */
7560 tgl@sss.pgh.pa.us 496 : 452525 : oldcontext = MemoryContextSwitchTo(ErrorContext);
497 : :
498 : : /* Collect backtrace, if enabled and we didn't already */
1619 alvherre@alvh.no-ip. 499 [ + - ]: 452525 : if (!edata->backtrace &&
106 peter@eisentraut.org 500 [ + - + - ]:GNC 452525 : ((edata->funcname &&
501 [ + - ]: 452525 : backtrace_functions &&
502 : 452525 : matches_backtrace_functions(edata->funcname)) ||
503 [ + + - + ]: 452525 : (edata->sqlerrcode == ERRCODE_INTERNAL_ERROR &&
504 : : backtrace_on_internal_error)))
1619 alvherre@alvh.no-ip. 505 :UBC 0 : set_backtrace(edata, 2);
506 : :
507 : : /*
508 : : * Call any context callback functions. Errors occurring in callback
509 : : * functions will be treated as recursive errors --- this ensures we will
510 : : * avoid infinite recursion (see errstart).
511 : : */
7661 tgl@sss.pgh.pa.us 512 :CBC 452525 : for (econtext = error_context_stack;
513 [ + + ]: 553622 : econtext != NULL;
514 : 101097 : econtext = econtext->previous)
2411 peter_e@gmx.net 515 : 101097 : econtext->callback(econtext->arg);
516 : :
517 : : /*
518 : : * If ERROR (not more nor less) we pass it off to the current handler.
519 : : * Printing it and popping the stack is the responsibility of the handler.
520 : : */
7161 tgl@sss.pgh.pa.us 521 [ + + ]: 452525 : if (elevel == ERROR)
522 : : {
523 : : /*
524 : : * We do some minimal cleanup before longjmp'ing so that handlers can
525 : : * execute in a reasonably sane state.
526 : : *
527 : : * Reset InterruptHoldoffCount in case we ereport'd from inside an
528 : : * interrupt holdoff section. (We assume here that no handler will
529 : : * itself be inside a holdoff section. If necessary, such a handler
530 : : * could save and restore InterruptHoldoffCount for itself, but this
531 : : * should make life easier for most.)
532 : : */
533 : 23290 : InterruptHoldoffCount = 0;
3359 heikki.linnakangas@i 534 : 23290 : QueryCancelHoldoffCount = 0;
535 : :
6756 bruce@momjian.us 536 : 23290 : CritSectionCount = 0; /* should be unnecessary, but... */
537 : :
538 : : /*
539 : : * Note that we leave CurrentMemoryContext set to ErrorContext. The
540 : : * handler should reset it to something else soon.
541 : : */
542 : :
7161 tgl@sss.pgh.pa.us 543 : 23290 : recursion_depth--;
544 : 23290 : PG_RE_THROW();
545 : : }
546 : :
547 : : /* Emit the message to the right places */
7197 548 : 429235 : EmitErrorReport();
549 : :
550 : : /* Now free up subsidiary data attached to stack entry, and release it */
494 551 : 429235 : FreeErrorDataContents(edata);
7661 552 : 429235 : errordata_stack_depth--;
553 : :
554 : : /* Exit error-handling context */
7197 555 : 429235 : MemoryContextSwitchTo(oldcontext);
7661 556 : 429235 : recursion_depth--;
557 : :
558 : : /*
559 : : * Perform error recovery action as specified by elevel.
560 : : */
7197 561 [ + + ]: 429235 : if (elevel == FATAL)
562 : : {
563 : : /*
564 : : * For a FATAL error, we let proc_exit clean up and exit.
565 : : *
566 : : * If we just reported a startup failure, the client will disconnect
567 : : * on receiving it, so don't send any more to the client.
568 : : */
6737 alvherre@alvh.no-ip. 569 [ + + + + ]: 792 : if (PG_exception_stack == NULL && whereToSendOutput == DestRemote)
570 : 321 : whereToSendOutput = DestNone;
571 : :
572 : : /*
573 : : * fflush here is just to improve the odds that we get to see the
574 : : * error message, in case things are so hosed that proc_exit crashes.
575 : : * Any other code you might be tempted to add here should probably be
576 : : * in an on_proc_exit or on_shmem_exit callback instead.
577 : : */
594 tgl@sss.pgh.pa.us 578 : 792 : fflush(NULL);
579 : :
580 : : /*
581 : : * Let the cumulative stats system know. Only mark the session as
582 : : * terminated by fatal error if there is no other known cause.
583 : : */
1183 magnus@hagander.net 584 [ + + ]: 792 : if (pgStatSessionEndCause == DISCONNECT_NORMAL)
585 : 696 : pgStatSessionEndCause = DISCONNECT_FATAL;
586 : :
587 : : /*
588 : : * Do normal process-exit cleanup, then return exit code 1 to indicate
589 : : * FATAL termination. The postmaster may or may not consider this
590 : : * worthy of panic, depending on which subprocess returns it.
591 : : */
6354 tgl@sss.pgh.pa.us 592 : 792 : proc_exit(1);
593 : : }
594 : :
7661 595 [ - + ]: 428443 : if (elevel >= PANIC)
596 : : {
597 : : /*
598 : : * Serious crash time. Postmaster will observe SIGABRT process exit
599 : : * status and kill the other backends too.
600 : : *
601 : : * XXX: what if we are *in* the postmaster? abort() won't kill our
602 : : * children...
603 : : */
594 tgl@sss.pgh.pa.us 604 :UBC 0 : fflush(NULL);
7835 605 : 0 : abort();
606 : : }
607 : :
608 : : /*
609 : : * Check for cancel/die interrupt first --- this is so that the user can
610 : : * stop a query emitting tons of notice or warning messages, even if it's
611 : : * in a loop that otherwise fails to check for interrupts.
612 : : */
6405 tgl@sss.pgh.pa.us 613 [ + + ]:CBC 428443 : CHECK_FOR_INTERRUPTS();
7661 614 : 428443 : }
615 : :
616 : :
617 : : /*
618 : : * errsave_start --- begin a "soft" error-reporting cycle
619 : : *
620 : : * If "context" isn't an ErrorSaveContext node, this behaves as
621 : : * errstart(ERROR, domain), and the errsave() macro ends up acting
622 : : * exactly like ereport(ERROR, ...).
623 : : *
624 : : * If "context" is an ErrorSaveContext node, but the node creator only wants
625 : : * notification of the fact of a soft error without any details, we just set
626 : : * the error_occurred flag in the ErrorSaveContext node and return false,
627 : : * which will cause us to skip the remaining error processing steps.
628 : : *
629 : : * Otherwise, create and initialize error stack entry and return true.
630 : : * Subsequently, errmsg() and perhaps other routines will be called to further
631 : : * populate the stack entry. Finally, errsave_finish() will be called to
632 : : * tidy up.
633 : : */
634 : : bool
492 635 : 25154 : errsave_start(struct Node *context, const char *domain)
636 : : {
637 : : ErrorSaveContext *escontext;
638 : : ErrorData *edata;
639 : :
640 : : /*
641 : : * Do we have a context for soft error reporting? If not, just punt to
642 : : * errstart().
643 : : */
644 [ + + - + ]: 25154 : if (context == NULL || !IsA(context, ErrorSaveContext))
645 : 3139 : return errstart(ERROR, domain);
646 : :
647 : : /* Report that a soft error was detected */
648 : 22015 : escontext = (ErrorSaveContext *) context;
649 : 22015 : escontext->error_occurred = true;
650 : :
651 : : /* Nothing else to do if caller wants no further details */
652 [ + + ]: 22015 : if (!escontext->details_wanted)
653 : 21660 : return false;
654 : :
655 : : /*
656 : : * Okay, crank up a stack entry to store the info in.
657 : : */
658 : :
659 : 355 : recursion_depth++;
660 : :
661 : : /* Initialize data for this error frame */
662 : 355 : edata = get_error_stack_entry();
663 : 355 : edata->elevel = LOG; /* signal all is well to errsave_finish */
664 : 355 : set_stack_entry_domain(edata, domain);
665 : : /* Select default errcode based on the assumed elevel of ERROR */
666 : 355 : edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
667 : :
668 : : /*
669 : : * Any allocations for this error state level should go into the caller's
670 : : * context. We don't need to pollute ErrorContext, or even require it to
671 : : * exist, in this code path.
672 : : */
673 : 355 : edata->assoc_context = CurrentMemoryContext;
674 : :
675 : 355 : recursion_depth--;
676 : 355 : return true;
677 : : }
678 : :
679 : : /*
680 : : * errsave_finish --- end a "soft" error-reporting cycle
681 : : *
682 : : * If errsave_start() decided this was a regular error, behave as
683 : : * errfinish(). Otherwise, package up the error details and save
684 : : * them in the ErrorSaveContext node.
685 : : */
686 : : void
687 : 3494 : errsave_finish(struct Node *context, const char *filename, int lineno,
688 : : const char *funcname)
689 : : {
690 : 3494 : ErrorSaveContext *escontext = (ErrorSaveContext *) context;
691 : 3494 : ErrorData *edata = &errordata[errordata_stack_depth];
692 : :
693 : : /* verify stack depth before accessing *edata */
694 [ - + - - ]: 3494 : CHECK_STACK_DEPTH();
695 : :
696 : : /*
697 : : * If errsave_start punted to errstart, then elevel will be ERROR or
698 : : * perhaps even PANIC. Punt likewise to errfinish.
699 : : */
700 [ + + ]: 3494 : if (edata->elevel >= ERROR)
701 : : {
702 : 3139 : errfinish(filename, lineno, funcname);
492 tgl@sss.pgh.pa.us 703 :UBC 0 : pg_unreachable();
704 : : }
705 : :
706 : : /*
707 : : * Else, we should package up the stack entry contents and deliver them to
708 : : * the caller.
709 : : */
492 tgl@sss.pgh.pa.us 710 :CBC 355 : recursion_depth++;
711 : :
712 : : /* Save the last few bits of error state into the stack entry */
713 : 355 : set_stack_entry_location(edata, filename, lineno, funcname);
714 : :
715 : : /* Replace the LOG value that errsave_start inserted */
716 : 355 : edata->elevel = ERROR;
717 : :
718 : : /*
719 : : * We skip calling backtrace and context functions, which are more likely
720 : : * to cause trouble than provide useful context; they might act on the
721 : : * assumption that a transaction abort is about to occur.
722 : : */
723 : :
724 : : /*
725 : : * Make a copy of the error info for the caller. All the subsidiary
726 : : * strings are already in the caller's context, so it's sufficient to
727 : : * flat-copy the stack entry.
728 : : */
729 : 355 : escontext->error_data = palloc_object(ErrorData);
730 : 355 : memcpy(escontext->error_data, edata, sizeof(ErrorData));
731 : :
732 : : /* Exit error-handling context */
733 : 355 : errordata_stack_depth--;
734 : 355 : recursion_depth--;
735 : 355 : }
736 : :
737 : :
738 : : /*
739 : : * get_error_stack_entry --- allocate and initialize a new stack entry
740 : : *
741 : : * The entry should be freed, when we're done with it, by calling
742 : : * FreeErrorDataContents() and then decrementing errordata_stack_depth.
743 : : *
744 : : * Returning the entry's address is just a notational convenience,
745 : : * since it had better be errordata[errordata_stack_depth].
746 : : *
747 : : * Although the error stack is not large, we don't expect to run out of space.
748 : : * Using more than one entry implies a new error report during error recovery,
749 : : * which is possible but already suggests we're in trouble. If we exhaust the
750 : : * stack, almost certainly we are in an infinite loop of errors during error
751 : : * recovery, so we give up and PANIC.
752 : : *
753 : : * (Note that this is distinct from the recursion_depth checks, which
754 : : * guard against recursion while handling a single stack entry.)
755 : : */
756 : : static ErrorData *
494 757 : 452936 : get_error_stack_entry(void)
758 : : {
759 : : ErrorData *edata;
760 : :
761 : : /* Allocate error frame */
762 : 452936 : errordata_stack_depth++;
763 [ - + ]: 452936 : if (unlikely(errordata_stack_depth >= ERRORDATA_STACK_SIZE))
764 : : {
765 : : /* Wups, stack not big enough */
494 tgl@sss.pgh.pa.us 766 :UBC 0 : errordata_stack_depth = -1; /* make room on stack */
767 [ # # ]: 0 : ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
768 : : }
769 : :
770 : : /* Initialize error frame to all zeroes/NULLs */
494 tgl@sss.pgh.pa.us 771 :CBC 452936 : edata = &errordata[errordata_stack_depth];
772 : 452936 : memset(edata, 0, sizeof(ErrorData));
773 : :
774 : : /* Save errno immediately to ensure error parameter eval can't change it */
775 : 452936 : edata->saved_errno = errno;
776 : :
777 : 452936 : return edata;
778 : : }
779 : :
780 : : /*
781 : : * set_stack_entry_domain --- fill in the internationalization domain
782 : : */
783 : : static void
784 : 452880 : set_stack_entry_domain(ErrorData *edata, const char *domain)
785 : : {
786 : : /* the default text domain is the backend's */
787 [ + + ]: 452880 : edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
788 : : /* initialize context_domain the same way (see set_errcontext_domain()) */
789 : 452880 : edata->context_domain = edata->domain;
790 : 452880 : }
791 : :
792 : : /*
793 : : * set_stack_entry_location --- fill in code-location details
794 : : *
795 : : * Store the values of __FILE__, __LINE__, and __func__ from the call site.
796 : : * We make an effort to normalize __FILE__, since compilers are inconsistent
797 : : * about how much of the path they'll include, and we'd prefer that the
798 : : * behavior not depend on that (especially, that it not vary with build path).
799 : : */
800 : : static void
801 : 452880 : set_stack_entry_location(ErrorData *edata,
802 : : const char *filename, int lineno,
803 : : const char *funcname)
804 : : {
805 [ + - ]: 452880 : if (filename)
806 : : {
807 : : const char *slash;
808 : :
809 : : /* keep only base name, useful especially for vpath builds */
810 : 452880 : slash = strrchr(filename, '/');
811 [ + + ]: 452880 : if (slash)
812 : 452877 : filename = slash + 1;
813 : : /* Some Windows compilers use backslashes in __FILE__ strings */
814 : 452880 : slash = strrchr(filename, '\\');
815 [ - + ]: 452880 : if (slash)
494 tgl@sss.pgh.pa.us 816 :UBC 0 : filename = slash + 1;
817 : : }
818 : :
494 tgl@sss.pgh.pa.us 819 :CBC 452880 : edata->filename = filename;
820 : 452880 : edata->lineno = lineno;
821 : 452880 : edata->funcname = funcname;
822 : 452880 : }
823 : :
824 : : /*
825 : : * matches_backtrace_functions --- checks whether the given funcname matches
826 : : * backtrace_functions
827 : : *
828 : : * See check_backtrace_functions.
829 : : */
830 : : static bool
831 : 452525 : matches_backtrace_functions(const char *funcname)
832 : : {
833 : : const char *p;
834 : :
108 peter@eisentraut.org 835 [ - + - - :GNC 452525 : if (!backtrace_function_list || funcname == NULL || funcname[0] == '\0')
- - ]
494 tgl@sss.pgh.pa.us 836 :CBC 452525 : return false;
837 : :
108 peter@eisentraut.org 838 :UNC 0 : p = backtrace_function_list;
839 : : for (;;)
840 : : {
841 [ # # ]: 0 : if (*p == '\0') /* end of backtrace_function_list */
494 tgl@sss.pgh.pa.us 842 :UBC 0 : break;
843 : :
844 [ # # ]: 0 : if (strcmp(funcname, p) == 0)
845 : 0 : return true;
846 : 0 : p += strlen(p) + 1;
847 : : }
848 : :
849 : 0 : return false;
850 : : }
851 : :
852 : :
853 : : /*
854 : : * errcode --- add SQLSTATE error code to the current error
855 : : *
856 : : * The code is expected to be represented as per MAKE_SQLSTATE().
857 : : */
858 : : int
7661 tgl@sss.pgh.pa.us 859 :CBC 25623 : errcode(int sqlerrcode)
860 : : {
861 : 25623 : ErrorData *edata = &errordata[errordata_stack_depth];
862 : :
863 : : /* we don't bother incrementing recursion_depth */
864 [ - + - - ]: 25623 : CHECK_STACK_DEPTH();
865 : :
866 : 25623 : edata->sqlerrcode = sqlerrcode;
867 : :
1481 868 : 25623 : return 0; /* return value does not matter */
869 : : }
870 : :
871 : :
872 : : /*
873 : : * errcode_for_file_access --- add SQLSTATE error code to the current error
874 : : *
875 : : * The SQLSTATE code is chosen based on the saved errno value. We assume
876 : : * that the failing operation was some type of disk file access.
877 : : *
878 : : * NOTE: the primary error message string should generally include %m
879 : : * when this is used.
880 : : */
881 : : int
7576 882 : 64 : errcode_for_file_access(void)
883 : : {
884 : 64 : ErrorData *edata = &errordata[errordata_stack_depth];
885 : :
886 : : /* we don't bother incrementing recursion_depth */
887 [ - + - - ]: 64 : CHECK_STACK_DEPTH();
888 : :
889 [ - + - + : 64 : switch (edata->saved_errno)
- - - -
+ ]
890 : : {
891 : : /* Permission-denied failures */
7576 tgl@sss.pgh.pa.us 892 :UBC 0 : case EPERM: /* Not super-user */
893 : : case EACCES: /* Permission denied */
894 : : #ifdef EROFS
895 : : case EROFS: /* Read only file system */
896 : : #endif
897 : 0 : edata->sqlerrcode = ERRCODE_INSUFFICIENT_PRIVILEGE;
898 : 0 : break;
899 : :
900 : : /* File not found */
7576 tgl@sss.pgh.pa.us 901 :CBC 50 : case ENOENT: /* No such file or directory */
7537 902 : 50 : edata->sqlerrcode = ERRCODE_UNDEFINED_FILE;
7576 903 : 50 : break;
904 : :
905 : : /* Duplicate file */
7576 tgl@sss.pgh.pa.us 906 :UBC 0 : case EEXIST: /* File exists */
7537 907 : 0 : edata->sqlerrcode = ERRCODE_DUPLICATE_FILE;
7576 908 : 0 : break;
909 : :
910 : : /* Wrong object type or state */
7576 tgl@sss.pgh.pa.us 911 :GBC 2 : case ENOTDIR: /* Not a directory */
912 : : case EISDIR: /* Is a directory */
913 : : case ENOTEMPTY: /* Directory not empty */
914 : 2 : edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE;
915 : 2 : break;
916 : :
917 : : /* Insufficient resources */
7576 tgl@sss.pgh.pa.us 918 :UBC 0 : case ENOSPC: /* No space left on device */
919 : 0 : edata->sqlerrcode = ERRCODE_DISK_FULL;
920 : 0 : break;
921 : :
72 922 : 0 : case ENOMEM: /* Out of memory */
923 : 0 : edata->sqlerrcode = ERRCODE_OUT_OF_MEMORY;
924 : 0 : break;
925 : :
7576 926 : 0 : case ENFILE: /* File table overflow */
927 : : case EMFILE: /* Too many open files */
928 : 0 : edata->sqlerrcode = ERRCODE_INSUFFICIENT_RESOURCES;
929 : 0 : break;
930 : :
931 : : /* Hardware failure */
932 : 0 : case EIO: /* I/O error */
933 : 0 : edata->sqlerrcode = ERRCODE_IO_ERROR;
934 : 0 : break;
935 : :
936 : : /* All else is classified as internal errors */
7576 tgl@sss.pgh.pa.us 937 :CBC 12 : default:
938 : 12 : edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
939 : 12 : break;
940 : : }
941 : :
1481 942 : 64 : return 0; /* return value does not matter */
943 : : }
944 : :
945 : : /*
946 : : * errcode_for_socket_access --- add SQLSTATE error code to the current error
947 : : *
948 : : * The SQLSTATE code is chosen based on the saved errno value. We assume
949 : : * that the failing operation was some type of socket access.
950 : : *
951 : : * NOTE: the primary error message string should generally include %m
952 : : * when this is used.
953 : : */
954 : : int
7572 955 : 32 : errcode_for_socket_access(void)
956 : : {
957 : 32 : ErrorData *edata = &errordata[errordata_stack_depth];
958 : :
959 : : /* we don't bother incrementing recursion_depth */
960 [ - + - - ]: 32 : CHECK_STACK_DEPTH();
961 : :
962 [ + - ]: 32 : switch (edata->saved_errno)
963 : : {
964 : : /* Loss of connection */
1282 965 : 32 : case ALL_CONNECTION_FAILURE_ERRNOS:
7572 966 : 32 : edata->sqlerrcode = ERRCODE_CONNECTION_FAILURE;
967 : 32 : break;
968 : :
969 : : /* All else is classified as internal errors */
7572 tgl@sss.pgh.pa.us 970 :UBC 0 : default:
971 : 0 : edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
972 : 0 : break;
973 : : }
974 : :
1481 tgl@sss.pgh.pa.us 975 :CBC 32 : return 0; /* return value does not matter */
976 : : }
977 : :
978 : :
979 : : /*
980 : : * This macro handles expansion of a format string and associated parameters;
981 : : * it's common code for errmsg(), errdetail(), etc. Must be called inside
982 : : * a routine that is declared like "const char *fmt, ..." and has an edata
983 : : * pointer set up. The message is assigned to edata->targetfield, or
984 : : * appended to it if appendval is true. The message is subject to translation
985 : : * if translateit is true.
986 : : *
987 : : * Note: we pstrdup the buffer rather than just transferring its storage
988 : : * to the edata field because the buffer might be considerably larger than
989 : : * really necessary.
990 : : */
991 : : #define EVALUATE_MESSAGE(domain, targetfield, appendval, translateit) \
992 : : { \
993 : : StringInfoData buf; \
994 : : /* Internationalize the error format string */ \
995 : : if ((translateit) && !in_error_recursion_trouble()) \
996 : : fmt = dgettext((domain), fmt); \
997 : : initStringInfo(&buf); \
998 : : if ((appendval) && edata->targetfield) { \
999 : : appendStringInfoString(&buf, edata->targetfield); \
1000 : : appendStringInfoChar(&buf, '\n'); \
1001 : : } \
1002 : : /* Generate actual output --- have to use appendStringInfoVA */ \
1003 : : for (;;) \
1004 : : { \
1005 : : va_list args; \
1006 : : int needed; \
1007 : : errno = edata->saved_errno; \
1008 : : va_start(args, fmt); \
1009 : : needed = appendStringInfoVA(&buf, fmt, args); \
1010 : : va_end(args); \
1011 : : if (needed == 0) \
1012 : : break; \
1013 : : enlargeStringInfo(&buf, needed); \
1014 : : } \
1015 : : /* Save the completed message into the stack item */ \
1016 : : if (edata->targetfield) \
1017 : : pfree(edata->targetfield); \
1018 : : edata->targetfield = pstrdup(buf.data); \
1019 : : pfree(buf.data); \
1020 : : }
1021 : :
1022 : : /*
1023 : : * Same as above, except for pluralized error messages. The calling routine
1024 : : * must be declared like "const char *fmt_singular, const char *fmt_plural,
1025 : : * unsigned long n, ...". Translation is assumed always wanted.
1026 : : */
1027 : : #define EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval) \
1028 : : { \
1029 : : const char *fmt; \
1030 : : StringInfoData buf; \
1031 : : /* Internationalize the error format string */ \
1032 : : if (!in_error_recursion_trouble()) \
1033 : : fmt = dngettext((domain), fmt_singular, fmt_plural, n); \
1034 : : else \
1035 : : fmt = (n == 1 ? fmt_singular : fmt_plural); \
1036 : : initStringInfo(&buf); \
1037 : : if ((appendval) && edata->targetfield) { \
1038 : : appendStringInfoString(&buf, edata->targetfield); \
1039 : : appendStringInfoChar(&buf, '\n'); \
1040 : : } \
1041 : : /* Generate actual output --- have to use appendStringInfoVA */ \
1042 : : for (;;) \
1043 : : { \
1044 : : va_list args; \
1045 : : int needed; \
1046 : : errno = edata->saved_errno; \
1047 : : va_start(args, n); \
1048 : : needed = appendStringInfoVA(&buf, fmt, args); \
1049 : : va_end(args); \
1050 : : if (needed == 0) \
1051 : : break; \
1052 : : enlargeStringInfo(&buf, needed); \
1053 : : } \
1054 : : /* Save the completed message into the stack item */ \
1055 : : if (edata->targetfield) \
1056 : : pfree(edata->targetfield); \
1057 : : edata->targetfield = pstrdup(buf.data); \
1058 : : pfree(buf.data); \
1059 : : }
1060 : :
1061 : :
1062 : : /*
1063 : : * errmsg --- add a primary error message text to the current error
1064 : : *
1065 : : * In addition to the usual %-escapes recognized by printf, "%m" in
1066 : : * fmt is replaced by the error message for the caller's value of errno.
1067 : : *
1068 : : * Note: no newline is needed at the end of the fmt string, since
1069 : : * ereport will provide one for the output methods that need it.
1070 : : */
1071 : : int
7559 bruce@momjian.us 1072 : 363564 : errmsg(const char *fmt,...)
1073 : : {
7661 tgl@sss.pgh.pa.us 1074 : 363564 : ErrorData *edata = &errordata[errordata_stack_depth];
1075 : : MemoryContext oldcontext;
1076 : :
1077 : 363564 : recursion_depth++;
1078 [ - + - - ]: 363564 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1079 : 363564 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1080 : :
2956 simon@2ndQuadrant.co 1081 : 363564 : edata->message_id = fmt;
4171 heikki.linnakangas@i 1082 [ + - + + : 364895 : EVALUATE_MESSAGE(edata->domain, message, false, true);
- + ]
1083 : :
7661 tgl@sss.pgh.pa.us 1084 : 363564 : MemoryContextSwitchTo(oldcontext);
1085 : 363564 : recursion_depth--;
1481 1086 : 363564 : return 0; /* return value does not matter */
1087 : : }
1088 : :
1089 : : /*
1090 : : * Add a backtrace to the containing ereport() call. This is intended to be
1091 : : * added temporarily during debugging.
1092 : : */
1093 : : int
1619 alvherre@alvh.no-ip. 1094 :UBC 0 : errbacktrace(void)
1095 : : {
1431 tgl@sss.pgh.pa.us 1096 : 0 : ErrorData *edata = &errordata[errordata_stack_depth];
1097 : : MemoryContext oldcontext;
1098 : :
1619 alvherre@alvh.no-ip. 1099 : 0 : recursion_depth++;
1100 [ # # # # ]: 0 : CHECK_STACK_DEPTH();
1101 : 0 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1102 : :
1103 : 0 : set_backtrace(edata, 1);
1104 : :
1105 : 0 : MemoryContextSwitchTo(oldcontext);
1106 : 0 : recursion_depth--;
1107 : :
1481 tgl@sss.pgh.pa.us 1108 : 0 : return 0;
1109 : : }
1110 : :
1111 : : /*
1112 : : * Compute backtrace data and add it to the supplied ErrorData. num_skip
1113 : : * specifies how many inner frames to skip. Use this to avoid showing the
1114 : : * internal backtrace support functions in the backtrace. This requires that
1115 : : * this and related functions are not inlined.
1116 : : */
1117 : : static void
1619 alvherre@alvh.no-ip. 1118 : 0 : set_backtrace(ErrorData *edata, int num_skip)
1119 : : {
1120 : : StringInfoData errtrace;
1121 : :
1122 : 0 : initStringInfo(&errtrace);
1123 : :
1124 : : #ifdef HAVE_BACKTRACE_SYMBOLS
1125 : : {
1126 : : void *buf[100];
1127 : : int nframes;
1128 : : char **strfrms;
1129 : :
1130 : 0 : nframes = backtrace(buf, lengthof(buf));
1131 : 0 : strfrms = backtrace_symbols(buf, nframes);
1132 [ # # ]: 0 : if (strfrms == NULL)
1133 : 0 : return;
1134 : :
1135 [ # # ]: 0 : for (int i = num_skip; i < nframes; i++)
1136 : 0 : appendStringInfo(&errtrace, "\n%s", strfrms[i]);
1137 : 0 : free(strfrms);
1138 : : }
1139 : : #else
1140 : : appendStringInfoString(&errtrace,
1141 : : "backtrace generation is not supported by this installation");
1142 : : #endif
1143 : :
1144 : 0 : edata->backtrace = errtrace.data;
1145 : : }
1146 : :
1147 : : /*
1148 : : * errmsg_internal --- add a primary error message text to the current error
1149 : : *
1150 : : * This is exactly like errmsg() except that strings passed to errmsg_internal
1151 : : * are not translated, and are customarily left out of the
1152 : : * internationalization message dictionary. This should be used for "can't
1153 : : * happen" cases that are probably not worth spending translation effort on.
1154 : : * We also use this for certain cases where we *must* not try to translate
1155 : : * the message because the translation would fail and result in infinite
1156 : : * error recursion.
1157 : : */
1158 : : int
7559 bruce@momjian.us 1159 :CBC 88927 : errmsg_internal(const char *fmt,...)
1160 : : {
7661 tgl@sss.pgh.pa.us 1161 : 88927 : ErrorData *edata = &errordata[errordata_stack_depth];
1162 : : MemoryContext oldcontext;
1163 : :
1164 : 88927 : recursion_depth++;
1165 [ - + - - ]: 88927 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1166 : 88927 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1167 : :
2956 simon@2ndQuadrant.co 1168 : 88927 : edata->message_id = fmt;
4171 heikki.linnakangas@i 1169 [ + + - + ]: 88938 : EVALUATE_MESSAGE(edata->domain, message, false, false);
1170 : :
7661 tgl@sss.pgh.pa.us 1171 : 88927 : MemoryContextSwitchTo(oldcontext);
1172 : 88927 : recursion_depth--;
1481 1173 : 88927 : return 0; /* return value does not matter */
1174 : : }
1175 : :
1176 : :
1177 : : /*
1178 : : * errmsg_plural --- add a primary error message text to the current error,
1179 : : * with support for pluralization of the message text
1180 : : */
1181 : : int
5428 1182 : 394 : errmsg_plural(const char *fmt_singular, const char *fmt_plural,
1183 : : unsigned long n,...)
1184 : : {
1185 : 394 : ErrorData *edata = &errordata[errordata_stack_depth];
1186 : : MemoryContext oldcontext;
1187 : :
1188 : 394 : recursion_depth++;
1189 [ - + - - ]: 394 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1190 : 394 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1191 : :
2956 simon@2ndQuadrant.co 1192 : 394 : edata->message_id = fmt_singular;
4171 heikki.linnakangas@i 1193 [ + - - - : 394 : EVALUATE_MESSAGE_PLURAL(edata->domain, message, false);
+ - - + ]
1194 : :
5428 tgl@sss.pgh.pa.us 1195 : 394 : MemoryContextSwitchTo(oldcontext);
1196 : 394 : recursion_depth--;
1481 1197 : 394 : return 0; /* return value does not matter */
1198 : : }
1199 : :
1200 : :
1201 : : /*
1202 : : * errdetail --- add a detail error message text to the current error
1203 : : */
1204 : : int
7559 bruce@momjian.us 1205 : 33408 : errdetail(const char *fmt,...)
1206 : : {
7661 tgl@sss.pgh.pa.us 1207 : 33408 : ErrorData *edata = &errordata[errordata_stack_depth];
1208 : : MemoryContext oldcontext;
1209 : :
1210 : 33408 : recursion_depth++;
1211 [ - + - - ]: 33408 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1212 : 33408 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1213 : :
4171 heikki.linnakangas@i 1214 [ + - + + : 33414 : EVALUATE_MESSAGE(edata->domain, detail, false, true);
- + ]
1215 : :
7661 tgl@sss.pgh.pa.us 1216 : 33408 : MemoryContextSwitchTo(oldcontext);
1217 : 33408 : recursion_depth--;
1481 1218 : 33408 : return 0; /* return value does not matter */
1219 : : }
1220 : :
1221 : :
1222 : : /*
1223 : : * errdetail_internal --- add a detail error message text to the current error
1224 : : *
1225 : : * This is exactly like errdetail() except that strings passed to
1226 : : * errdetail_internal are not translated, and are customarily left out of the
1227 : : * internationalization message dictionary. This should be used for detail
1228 : : * messages that seem not worth translating for one reason or another
1229 : : * (typically, that they don't seem to be useful to average users).
1230 : : */
1231 : : int
4656 1232 : 1471 : errdetail_internal(const char *fmt,...)
1233 : : {
1234 : 1471 : ErrorData *edata = &errordata[errordata_stack_depth];
1235 : : MemoryContext oldcontext;
1236 : :
1237 : 1471 : recursion_depth++;
1238 [ - + - - ]: 1471 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1239 : 1471 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1240 : :
4171 heikki.linnakangas@i 1241 [ + + - + ]: 1480 : EVALUATE_MESSAGE(edata->domain, detail, false, false);
1242 : :
4656 tgl@sss.pgh.pa.us 1243 : 1471 : MemoryContextSwitchTo(oldcontext);
1244 : 1471 : recursion_depth--;
1481 1245 : 1471 : return 0; /* return value does not matter */
1246 : : }
1247 : :
1248 : :
1249 : : /*
1250 : : * errdetail_log --- add a detail_log error message text to the current error
1251 : : */
1252 : : int
5865 1253 : 579 : errdetail_log(const char *fmt,...)
1254 : : {
1255 : 579 : ErrorData *edata = &errordata[errordata_stack_depth];
1256 : : MemoryContext oldcontext;
1257 : :
1258 : 579 : recursion_depth++;
1259 [ - + - - ]: 579 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1260 : 579 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1261 : :
4171 heikki.linnakangas@i 1262 [ + - + + : 589 : EVALUATE_MESSAGE(edata->domain, detail_log, false, true);
- + ]
1263 : :
5865 tgl@sss.pgh.pa.us 1264 : 579 : MemoryContextSwitchTo(oldcontext);
1265 : 579 : recursion_depth--;
1481 1266 : 579 : return 0; /* return value does not matter */
1267 : : }
1268 : :
1269 : : /*
1270 : : * errdetail_log_plural --- add a detail_log error message text to the current error
1271 : : * with support for pluralization of the message text
1272 : : */
1273 : : int
3685 fujii@postgresql.org 1274 : 16 : errdetail_log_plural(const char *fmt_singular, const char *fmt_plural,
1275 : : unsigned long n,...)
1276 : : {
1277 : 16 : ErrorData *edata = &errordata[errordata_stack_depth];
1278 : : MemoryContext oldcontext;
1279 : :
1280 : 16 : recursion_depth++;
1281 [ - + - - ]: 16 : CHECK_STACK_DEPTH();
1282 : 16 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1283 : :
1284 [ + - - - : 16 : EVALUATE_MESSAGE_PLURAL(edata->domain, detail_log, false);
+ - - + ]
1285 : :
1286 : 16 : MemoryContextSwitchTo(oldcontext);
1287 : 16 : recursion_depth--;
1481 tgl@sss.pgh.pa.us 1288 : 16 : return 0; /* return value does not matter */
1289 : : }
1290 : :
1291 : :
1292 : : /*
1293 : : * errdetail_plural --- add a detail error message text to the current error,
1294 : : * with support for pluralization of the message text
1295 : : */
1296 : : int
5428 1297 : 24 : errdetail_plural(const char *fmt_singular, const char *fmt_plural,
1298 : : unsigned long n,...)
1299 : : {
1300 : 24 : ErrorData *edata = &errordata[errordata_stack_depth];
1301 : : MemoryContext oldcontext;
1302 : :
1303 : 24 : recursion_depth++;
1304 [ - + - - ]: 24 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1305 : 24 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1306 : :
4171 heikki.linnakangas@i 1307 [ + - - - : 24 : EVALUATE_MESSAGE_PLURAL(edata->domain, detail, false);
+ - - + ]
1308 : :
5428 tgl@sss.pgh.pa.us 1309 : 24 : MemoryContextSwitchTo(oldcontext);
1310 : 24 : recursion_depth--;
1481 1311 : 24 : return 0; /* return value does not matter */
1312 : : }
1313 : :
1314 : :
1315 : : /*
1316 : : * errhint --- add a hint error message text to the current error
1317 : : */
1318 : : int
7559 bruce@momjian.us 1319 : 145433 : errhint(const char *fmt,...)
1320 : : {
7661 tgl@sss.pgh.pa.us 1321 : 145433 : ErrorData *edata = &errordata[errordata_stack_depth];
1322 : : MemoryContext oldcontext;
1323 : :
1324 : 145433 : recursion_depth++;
1325 [ - + - - ]: 145433 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1326 : 145433 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1327 : :
4171 heikki.linnakangas@i 1328 [ + - + - : 145433 : EVALUATE_MESSAGE(edata->domain, hint, false, true);
- + ]
1329 : :
7661 tgl@sss.pgh.pa.us 1330 : 145433 : MemoryContextSwitchTo(oldcontext);
1331 : 145433 : recursion_depth--;
1481 1332 : 145433 : return 0; /* return value does not matter */
1333 : : }
1334 : :
1335 : :
1336 : : /*
1337 : : * errhint_plural --- add a hint error message text to the current error,
1338 : : * with support for pluralization of the message text
1339 : : */
1340 : : int
1110 peter@eisentraut.org 1341 :UBC 0 : errhint_plural(const char *fmt_singular, const char *fmt_plural,
1342 : : unsigned long n,...)
1343 : : {
1344 : 0 : ErrorData *edata = &errordata[errordata_stack_depth];
1345 : : MemoryContext oldcontext;
1346 : :
1347 : 0 : recursion_depth++;
1348 [ # # # # ]: 0 : CHECK_STACK_DEPTH();
1349 : 0 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1350 : :
1351 [ # # # # : 0 : EVALUATE_MESSAGE_PLURAL(edata->domain, hint, false);
# # # # ]
1352 : :
1353 : 0 : MemoryContextSwitchTo(oldcontext);
1354 : 0 : recursion_depth--;
1355 : 0 : return 0; /* return value does not matter */
1356 : : }
1357 : :
1358 : :
1359 : : /*
1360 : : * errcontext_msg --- add a context error message text to the current error
1361 : : *
1362 : : * Unlike other cases, multiple calls are allowed to build up a stack of
1363 : : * context information. We assume earlier calls represent more-closely-nested
1364 : : * states.
1365 : : */
1366 : : int
4171 heikki.linnakangas@i 1367 :CBC 20591 : errcontext_msg(const char *fmt,...)
1368 : : {
7661 tgl@sss.pgh.pa.us 1369 : 20591 : ErrorData *edata = &errordata[errordata_stack_depth];
1370 : : MemoryContext oldcontext;
1371 : :
1372 : 20591 : recursion_depth++;
1373 [ - + - - ]: 20591 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1374 : 20591 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1375 : :
4171 heikki.linnakangas@i 1376 [ + - + + : 41203 : EVALUATE_MESSAGE(edata->context_domain, context, true, true);
+ + + + ]
1377 : :
7661 tgl@sss.pgh.pa.us 1378 : 20591 : MemoryContextSwitchTo(oldcontext);
1379 : 20591 : recursion_depth--;
1481 1380 : 20591 : return 0; /* return value does not matter */
1381 : : }
1382 : :
1383 : : /*
1384 : : * set_errcontext_domain --- set message domain to be used by errcontext()
1385 : : *
1386 : : * errcontext_msg() can be called from a different module than the original
1387 : : * ereport(), so we cannot use the message domain passed in errstart() to
1388 : : * translate it. Instead, each errcontext_msg() call should be preceded by
1389 : : * a set_errcontext_domain() call to specify the domain. This is usually
1390 : : * done transparently by the errcontext() macro.
1391 : : */
1392 : : int
4171 heikki.linnakangas@i 1393 : 20591 : set_errcontext_domain(const char *domain)
1394 : : {
1395 : 20591 : ErrorData *edata = &errordata[errordata_stack_depth];
1396 : :
1397 : : /* we don't bother incrementing recursion_depth */
1398 [ - + - - ]: 20591 : CHECK_STACK_DEPTH();
1399 : :
1400 : : /* the default text domain is the backend's */
3380 tgl@sss.pgh.pa.us 1401 [ + + ]: 20591 : edata->context_domain = domain ? domain : PG_TEXTDOMAIN("postgres");
1402 : :
1481 1403 : 20591 : return 0; /* return value does not matter */
1404 : : }
1405 : :
1406 : :
1407 : : /*
1408 : : * errhidestmt --- optionally suppress STATEMENT: field of log entry
1409 : : *
1410 : : * This should be called if the message text already includes the statement.
1411 : : */
1412 : : int
6253 1413 : 175110 : errhidestmt(bool hide_stmt)
1414 : : {
1415 : 175110 : ErrorData *edata = &errordata[errordata_stack_depth];
1416 : :
1417 : : /* we don't bother incrementing recursion_depth */
1418 [ - + - - ]: 175110 : CHECK_STACK_DEPTH();
1419 : :
1420 : 175110 : edata->hide_stmt = hide_stmt;
1421 : :
1481 1422 : 175110 : return 0; /* return value does not matter */
1423 : : }
1424 : :
1425 : : /*
1426 : : * errhidecontext --- optionally suppress CONTEXT: field of log entry
1427 : : *
1428 : : * This should only be used for verbose debugging messages where the repeated
1429 : : * inclusion of context would bloat the log volume too much.
1430 : : */
1431 : : int
3398 andres@anarazel.de 1432 : 792 : errhidecontext(bool hide_ctx)
1433 : : {
1434 : 792 : ErrorData *edata = &errordata[errordata_stack_depth];
1435 : :
1436 : : /* we don't bother incrementing recursion_depth */
1437 [ - + - - ]: 792 : CHECK_STACK_DEPTH();
1438 : :
1439 : 792 : edata->hide_ctx = hide_ctx;
1440 : :
1481 tgl@sss.pgh.pa.us 1441 : 792 : return 0; /* return value does not matter */
1442 : : }
1443 : :
1444 : : /*
1445 : : * errposition --- add cursor position to the current error
1446 : : */
1447 : : int
7661 1448 : 4998 : errposition(int cursorpos)
1449 : : {
1450 : 4998 : ErrorData *edata = &errordata[errordata_stack_depth];
1451 : :
1452 : : /* we don't bother incrementing recursion_depth */
1453 [ - + - - ]: 4998 : CHECK_STACK_DEPTH();
1454 : :
1455 : 4998 : edata->cursorpos = cursorpos;
1456 : :
1481 1457 : 4998 : return 0; /* return value does not matter */
1458 : : }
1459 : :
1460 : : /*
1461 : : * internalerrposition --- add internal cursor position to the current error
1462 : : */
1463 : : int
7329 1464 : 254 : internalerrposition(int cursorpos)
1465 : : {
1466 : 254 : ErrorData *edata = &errordata[errordata_stack_depth];
1467 : :
1468 : : /* we don't bother incrementing recursion_depth */
1469 [ - + - - ]: 254 : CHECK_STACK_DEPTH();
1470 : :
1471 : 254 : edata->internalpos = cursorpos;
1472 : :
1481 1473 : 254 : return 0; /* return value does not matter */
1474 : : }
1475 : :
1476 : : /*
1477 : : * internalerrquery --- add internal query text to the current error
1478 : : *
1479 : : * Can also pass NULL to drop the internal query text entry. This case
1480 : : * is intended for use in error callback subroutines that are editorializing
1481 : : * on the layout of the error report.
1482 : : */
1483 : : int
7329 1484 : 245 : internalerrquery(const char *query)
1485 : : {
1486 : 245 : ErrorData *edata = &errordata[errordata_stack_depth];
1487 : :
1488 : : /* we don't bother incrementing recursion_depth */
1489 [ - + - - ]: 245 : CHECK_STACK_DEPTH();
1490 : :
1491 [ + + ]: 245 : if (edata->internalquery)
1492 : : {
1493 : 86 : pfree(edata->internalquery);
1494 : 86 : edata->internalquery = NULL;
1495 : : }
1496 : :
1497 [ + + ]: 245 : if (query)
3909 sfrost@snowman.net 1498 : 144 : edata->internalquery = MemoryContextStrdup(edata->assoc_context, query);
1499 : :
1481 tgl@sss.pgh.pa.us 1500 : 245 : return 0; /* return value does not matter */
1501 : : }
1502 : :
1503 : : /*
1504 : : * err_generic_string -- used to set individual ErrorData string fields
1505 : : * identified by PG_DIAG_xxx codes.
1506 : : *
1507 : : * This intentionally only supports fields that don't use localized strings,
1508 : : * so that there are no translation considerations.
1509 : : *
1510 : : * Most potential callers should not use this directly, but instead prefer
1511 : : * higher-level abstractions, such as errtablecol() (see relcache.c).
1512 : : */
1513 : : int
4093 1514 : 5705 : err_generic_string(int field, const char *str)
1515 : : {
1516 : 5705 : ErrorData *edata = &errordata[errordata_stack_depth];
1517 : :
1518 : : /* we don't bother incrementing recursion_depth */
1519 [ - + - - ]: 5705 : CHECK_STACK_DEPTH();
1520 : :
1521 [ + + + + : 5705 : switch (field)
+ - ]
1522 : : {
1523 : 2006 : case PG_DIAG_SCHEMA_NAME:
3909 sfrost@snowman.net 1524 : 2006 : set_errdata_field(edata->assoc_context, &edata->schema_name, str);
4093 tgl@sss.pgh.pa.us 1525 : 2006 : break;
1526 : 1640 : case PG_DIAG_TABLE_NAME:
3909 sfrost@snowman.net 1527 : 1640 : set_errdata_field(edata->assoc_context, &edata->table_name, str);
4093 tgl@sss.pgh.pa.us 1528 : 1640 : break;
1529 : 210 : case PG_DIAG_COLUMN_NAME:
3909 sfrost@snowman.net 1530 : 210 : set_errdata_field(edata->assoc_context, &edata->column_name, str);
4093 tgl@sss.pgh.pa.us 1531 : 210 : break;
1532 : 383 : case PG_DIAG_DATATYPE_NAME:
3909 sfrost@snowman.net 1533 : 383 : set_errdata_field(edata->assoc_context, &edata->datatype_name, str);
4093 tgl@sss.pgh.pa.us 1534 : 383 : break;
1535 : 1466 : case PG_DIAG_CONSTRAINT_NAME:
3909 sfrost@snowman.net 1536 : 1466 : set_errdata_field(edata->assoc_context, &edata->constraint_name, str);
4093 tgl@sss.pgh.pa.us 1537 : 1466 : break;
4093 tgl@sss.pgh.pa.us 1538 :UBC 0 : default:
1539 [ # # ]: 0 : elog(ERROR, "unsupported ErrorData field id: %d", field);
1540 : : break;
1541 : : }
1542 : :
1481 tgl@sss.pgh.pa.us 1543 :CBC 5705 : return 0; /* return value does not matter */
1544 : : }
1545 : :
1546 : : /*
1547 : : * set_errdata_field --- set an ErrorData string field
1548 : : */
1549 : : static void
3909 sfrost@snowman.net 1550 : 5705 : set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str)
1551 : : {
4093 tgl@sss.pgh.pa.us 1552 [ - + ]: 5705 : Assert(*ptr == NULL);
3909 sfrost@snowman.net 1553 : 5705 : *ptr = MemoryContextStrdup(cxt, str);
4093 tgl@sss.pgh.pa.us 1554 : 5705 : }
1555 : :
1556 : : /*
1557 : : * geterrcode --- return the currently set SQLSTATE error code
1558 : : *
1559 : : * This is only intended for use in error callback subroutines, since there
1560 : : * is no other place outside elog.c where the concept is meaningful.
1561 : : */
1562 : : int
5704 1563 : 2446 : geterrcode(void)
1564 : : {
1565 : 2446 : ErrorData *edata = &errordata[errordata_stack_depth];
1566 : :
1567 : : /* we don't bother incrementing recursion_depth */
1568 [ - + - - ]: 2446 : CHECK_STACK_DEPTH();
1569 : :
1570 : 2446 : return edata->sqlerrcode;
1571 : : }
1572 : :
1573 : : /*
1574 : : * geterrposition --- return the currently set error position (0 if none)
1575 : : *
1576 : : * This is only intended for use in error callback subroutines, since there
1577 : : * is no other place outside elog.c where the concept is meaningful.
1578 : : */
1579 : : int
7329 1580 : 7742 : geterrposition(void)
1581 : : {
1582 : 7742 : ErrorData *edata = &errordata[errordata_stack_depth];
1583 : :
1584 : : /* we don't bother incrementing recursion_depth */
1585 [ - + - - ]: 7742 : CHECK_STACK_DEPTH();
1586 : :
1587 : 7742 : return edata->cursorpos;
1588 : : }
1589 : :
1590 : : /*
1591 : : * getinternalerrposition --- same for internal error position
1592 : : *
1593 : : * This is only intended for use in error callback subroutines, since there
1594 : : * is no other place outside elog.c where the concept is meaningful.
1595 : : */
1596 : : int
1597 : 127 : getinternalerrposition(void)
1598 : : {
1599 : 127 : ErrorData *edata = &errordata[errordata_stack_depth];
1600 : :
1601 : : /* we don't bother incrementing recursion_depth */
1602 [ - + - - ]: 127 : CHECK_STACK_DEPTH();
1603 : :
1604 : 127 : return edata->internalpos;
1605 : : }
1606 : :
1607 : :
1608 : : /*
1609 : : * Functions to allow construction of error message strings separately from
1610 : : * the ereport() call itself.
1611 : : *
1612 : : * The expected calling convention is
1613 : : *
1614 : : * pre_format_elog_string(errno, domain), var = format_elog_string(format,...)
1615 : : *
1616 : : * which can be hidden behind a macro such as GUC_check_errdetail(). We
1617 : : * assume that any functions called in the arguments of format_elog_string()
1618 : : * cannot result in re-entrant use of these functions --- otherwise the wrong
1619 : : * text domain might be used, or the wrong errno substituted for %m. This is
1620 : : * okay for the current usage with GUC check hooks, but might need further
1621 : : * effort someday.
1622 : : *
1623 : : * The result of format_elog_string() is stored in ErrorContext, and will
1624 : : * therefore survive until FlushErrorState() is called.
1625 : : */
1626 : : static int save_format_errnumber;
1627 : : static const char *save_format_domain;
1628 : :
1629 : : void
4756 1630 : 27 : pre_format_elog_string(int errnumber, const char *domain)
1631 : : {
1632 : : /* Save errno before evaluation of argument functions can change it */
1633 : 27 : save_format_errnumber = errnumber;
1634 : : /* Save caller's text domain */
1635 : 27 : save_format_domain = domain;
1636 : 27 : }
1637 : :
1638 : : char *
4753 bruce@momjian.us 1639 : 27 : format_elog_string(const char *fmt,...)
1640 : : {
1641 : : ErrorData errdata;
1642 : : ErrorData *edata;
1643 : : MemoryContext oldcontext;
1644 : :
1645 : : /* Initialize a mostly-dummy error frame */
4756 tgl@sss.pgh.pa.us 1646 : 27 : edata = &errdata;
1647 [ + - + - : 648 : MemSet(edata, 0, sizeof(ErrorData));
+ - + - +
+ ]
1648 : : /* the default text domain is the backend's */
1649 [ - + ]: 27 : edata->domain = save_format_domain ? save_format_domain : PG_TEXTDOMAIN("postgres");
1650 : : /* set the errno to be used to interpret %m */
1651 : 27 : edata->saved_errno = save_format_errnumber;
1652 : :
1653 : 27 : oldcontext = MemoryContextSwitchTo(ErrorContext);
1654 : :
2956 simon@2ndQuadrant.co 1655 : 27 : edata->message_id = fmt;
4171 heikki.linnakangas@i 1656 [ + - + - : 27 : EVALUATE_MESSAGE(edata->domain, message, false, true);
- + ]
1657 : :
4756 tgl@sss.pgh.pa.us 1658 : 27 : MemoryContextSwitchTo(oldcontext);
1659 : :
1660 : 27 : return edata->message;
1661 : : }
1662 : :
1663 : :
1664 : : /*
1665 : : * Actual output of the top-of-stack error message
1666 : : *
1667 : : * In the ereport(ERROR) case this is called from PostgresMain (or not at all,
1668 : : * if the error is caught by somebody). For all other severity levels this
1669 : : * is called by errfinish.
1670 : : */
1671 : : void
7197 1672 : 449384 : EmitErrorReport(void)
1673 : : {
1674 : 449384 : ErrorData *edata = &errordata[errordata_stack_depth];
1675 : : MemoryContext oldcontext;
1676 : :
1677 : 449384 : recursion_depth++;
1678 [ - + - - ]: 449384 : CHECK_STACK_DEPTH();
3909 sfrost@snowman.net 1679 : 449384 : oldcontext = MemoryContextSwitchTo(edata->assoc_context);
1680 : :
1681 : : /*
1682 : : * Reset the formatted timestamp fields before emitting any logs. This
1683 : : * includes all the log destinations and emit_log_hook, as the latter
1684 : : * could use log_line_prefix or the formatted timestamps.
1685 : : */
10 michael@paquier.xyz 1686 :GNC 449384 : saved_timeval_set = false;
1687 : 449384 : formatted_log_time[0] = '\0';
1688 : :
1689 : : /*
1690 : : * Call hook before sending message to log. The hook function is allowed
1691 : : * to turn off edata->output_to_server, so we must recheck that afterward.
1692 : : * Making any other change in the content of edata is not considered
1693 : : * supported.
1694 : : *
1695 : : * Note: the reason why the hook can only turn off output_to_server, and
1696 : : * not turn it on, is that it'd be unreliable: we will never get here at
1697 : : * all if errstart() deems the message uninteresting. A hook that could
1698 : : * make decisions in that direction would have to hook into errstart(),
1699 : : * where it would have much less information available. emit_log_hook is
1700 : : * intended for custom log filtering and custom log message transmission
1701 : : * mechanisms.
1702 : : *
1703 : : * The log hook has access to both the translated and original English
1704 : : * error message text, which is passed through to allow it to be used as a
1705 : : * message identifier. Note that the original text is not available for
1706 : : * detail, detail_log, hint and context text elements.
1707 : : */
4422 tgl@sss.pgh.pa.us 1708 [ + + - + ]:CBC 449384 : if (edata->output_to_server && emit_log_hook)
4422 tgl@sss.pgh.pa.us 1709 :UBC 0 : (*emit_log_hook) (edata);
1710 : :
1711 : : /* Send to server log, if enabled */
7197 tgl@sss.pgh.pa.us 1712 [ + + ]:CBC 449384 : if (edata->output_to_server)
1713 : 438121 : send_message_to_server_log(edata);
1714 : :
1715 : : /* Send to client, if enabled */
1716 [ + + ]: 449384 : if (edata->output_to_client)
1717 : 97914 : send_message_to_frontend(edata);
1718 : :
1719 : 449384 : MemoryContextSwitchTo(oldcontext);
1720 : 449384 : recursion_depth--;
1721 : 449384 : }
1722 : :
1723 : : /*
1724 : : * CopyErrorData --- obtain a copy of the topmost error stack entry
1725 : : *
1726 : : * This is only for use in error handler code. The data is copied into the
1727 : : * current memory context, so callers should always switch away from
1728 : : * ErrorContext first; otherwise it will be lost when FlushErrorState is done.
1729 : : */
1730 : : ErrorData *
1731 : 3184 : CopyErrorData(void)
1732 : : {
1733 : 3184 : ErrorData *edata = &errordata[errordata_stack_depth];
1734 : : ErrorData *newedata;
1735 : :
1736 : : /*
1737 : : * we don't increment recursion_depth because out-of-memory here does not
1738 : : * indicate a problem within the error subsystem.
1739 : : */
1740 [ - + - - ]: 3184 : CHECK_STACK_DEPTH();
1741 : :
1742 [ - + ]: 3184 : Assert(CurrentMemoryContext != ErrorContext);
1743 : :
1744 : : /* Copy the struct itself */
1745 : 3184 : newedata = (ErrorData *) palloc(sizeof(ErrorData));
1746 : 3184 : memcpy(newedata, edata, sizeof(ErrorData));
1747 : :
1748 : : /* Make copies of separately-allocated fields */
1749 [ + - ]: 3184 : if (newedata->message)
1750 : 3184 : newedata->message = pstrdup(newedata->message);
1751 [ + + ]: 3184 : if (newedata->detail)
1752 : 83 : newedata->detail = pstrdup(newedata->detail);
5865 1753 [ - + ]: 3184 : if (newedata->detail_log)
5865 tgl@sss.pgh.pa.us 1754 :UBC 0 : newedata->detail_log = pstrdup(newedata->detail_log);
7197 tgl@sss.pgh.pa.us 1755 [ + + ]:CBC 3184 : if (newedata->hint)
1756 : 27 : newedata->hint = pstrdup(newedata->hint);
1757 [ + + ]: 3184 : if (newedata->context)
1758 : 3166 : newedata->context = pstrdup(newedata->context);
1619 alvherre@alvh.no-ip. 1759 [ - + ]: 3184 : if (newedata->backtrace)
1619 alvherre@alvh.no-ip. 1760 :UBC 0 : newedata->backtrace = pstrdup(newedata->backtrace);
4093 tgl@sss.pgh.pa.us 1761 [ + + ]:CBC 3184 : if (newedata->schema_name)
1762 : 28 : newedata->schema_name = pstrdup(newedata->schema_name);
1763 [ + + ]: 3184 : if (newedata->table_name)
1764 : 30 : newedata->table_name = pstrdup(newedata->table_name);
1765 [ + + ]: 3184 : if (newedata->column_name)
1766 : 9 : newedata->column_name = pstrdup(newedata->column_name);
1767 [ + + ]: 3184 : if (newedata->datatype_name)
1768 : 10 : newedata->datatype_name = pstrdup(newedata->datatype_name);
1769 [ + + ]: 3184 : if (newedata->constraint_name)
1770 : 27 : newedata->constraint_name = pstrdup(newedata->constraint_name);
7197 1771 [ + + ]: 3184 : if (newedata->internalquery)
1772 : 15 : newedata->internalquery = pstrdup(newedata->internalquery);
1773 : :
1774 : : /* Use the calling context for string allocation */
3909 sfrost@snowman.net 1775 : 3184 : newedata->assoc_context = CurrentMemoryContext;
1776 : :
7197 tgl@sss.pgh.pa.us 1777 : 3184 : return newedata;
1778 : : }
1779 : :
1780 : : /*
1781 : : * FreeErrorData --- free the structure returned by CopyErrorData.
1782 : : *
1783 : : * Error handlers should use this in preference to assuming they know all
1784 : : * the separately-allocated fields.
1785 : : */
1786 : : void
1787 : 70 : FreeErrorData(ErrorData *edata)
1788 : : {
494 1789 : 70 : FreeErrorDataContents(edata);
1790 : 70 : pfree(edata);
1791 : 70 : }
1792 : :
1793 : : /*
1794 : : * FreeErrorDataContents --- free the subsidiary data of an ErrorData.
1795 : : *
1796 : : * This can be used on either an error stack entry or a copied ErrorData.
1797 : : */
1798 : : static void
1799 : 429313 : FreeErrorDataContents(ErrorData *edata)
1800 : : {
7197 1801 [ + - ]: 429313 : if (edata->message)
1802 : 429313 : pfree(edata->message);
1803 [ + + ]: 429313 : if (edata->detail)
1804 : 30318 : pfree(edata->detail);
5865 1805 [ + + ]: 429313 : if (edata->detail_log)
1806 : 374 : pfree(edata->detail_log);
7197 1807 [ + + ]: 429313 : if (edata->hint)
1808 : 143354 : pfree(edata->hint);
1809 [ + + ]: 429313 : if (edata->context)
1810 : 8210 : pfree(edata->context);
1619 alvherre@alvh.no-ip. 1811 [ - + ]: 429313 : if (edata->backtrace)
1619 alvherre@alvh.no-ip. 1812 :UBC 0 : pfree(edata->backtrace);
4093 tgl@sss.pgh.pa.us 1813 [ + + ]:CBC 429313 : if (edata->schema_name)
1814 : 19 : pfree(edata->schema_name);
1815 [ + + ]: 429313 : if (edata->table_name)
1816 : 21 : pfree(edata->table_name);
1817 [ + + ]: 429313 : if (edata->column_name)
1818 : 6 : pfree(edata->column_name);
1819 [ + + ]: 429313 : if (edata->datatype_name)
1820 : 7 : pfree(edata->datatype_name);
1821 [ + + ]: 429313 : if (edata->constraint_name)
1822 : 12 : pfree(edata->constraint_name);
7197 1823 [ + + ]: 429313 : if (edata->internalquery)
1824 : 17 : pfree(edata->internalquery);
1825 : 429313 : }
1826 : :
1827 : : /*
1828 : : * FlushErrorState --- flush the error state after error recovery
1829 : : *
1830 : : * This should be called by an error handler after it's done processing
1831 : : * the error; or as soon as it's done CopyErrorData, if it intends to
1832 : : * do stuff that is likely to provoke another error. You are not "out" of
1833 : : * the error subsystem until you have done this.
1834 : : */
1835 : : void
1836 : 23162 : FlushErrorState(void)
1837 : : {
1838 : : /*
1839 : : * Reset stack to empty. The only case where it would be more than one
1840 : : * deep is if we serviced an error that interrupted construction of
1841 : : * another message. We assume control escaped out of that message
1842 : : * construction and won't ever go back.
1843 : : */
1844 : 23162 : errordata_stack_depth = -1;
1845 : 23162 : recursion_depth = 0;
1846 : : /* Delete all data in ErrorContext */
151 nathan@postgresql.or 1847 :GNC 23162 : MemoryContextReset(ErrorContext);
7197 tgl@sss.pgh.pa.us 1848 :CBC 23162 : }
1849 : :
1850 : : /*
1851 : : * ThrowErrorData --- report an error described by an ErrorData structure
1852 : : *
1853 : : * This is somewhat like ReThrowError, but it allows elevels besides ERROR,
1854 : : * and the boolean flags such as output_to_server are computed via the
1855 : : * default rules rather than being copied from the given ErrorData.
1856 : : * This is primarily used to re-report errors originally reported by
1857 : : * background worker processes and then propagated (with or without
1858 : : * modification) to the backend responsible for them.
1859 : : */
1860 : : void
3453 rhaas@postgresql.org 1861 : 3 : ThrowErrorData(ErrorData *edata)
1862 : : {
1863 : : ErrorData *newedata;
1864 : : MemoryContext oldcontext;
1865 : :
1482 tgl@sss.pgh.pa.us 1866 [ - + ]: 3 : if (!errstart(edata->elevel, edata->domain))
2788 tgl@sss.pgh.pa.us 1867 :UBC 0 : return; /* error is not to be reported at all */
1868 : :
3453 rhaas@postgresql.org 1869 :CBC 3 : newedata = &errordata[errordata_stack_depth];
2788 tgl@sss.pgh.pa.us 1870 : 3 : recursion_depth++;
1871 : 3 : oldcontext = MemoryContextSwitchTo(newedata->assoc_context);
1872 : :
1873 : : /* Copy the supplied fields to the error stack entry. */
1874 [ + - ]: 3 : if (edata->sqlerrcode != 0)
3453 rhaas@postgresql.org 1875 : 3 : newedata->sqlerrcode = edata->sqlerrcode;
1876 [ + - ]: 3 : if (edata->message)
1877 : 3 : newedata->message = pstrdup(edata->message);
1878 [ - + ]: 3 : if (edata->detail)
3453 rhaas@postgresql.org 1879 :UBC 0 : newedata->detail = pstrdup(edata->detail);
3453 rhaas@postgresql.org 1880 [ - + ]:CBC 3 : if (edata->detail_log)
3453 rhaas@postgresql.org 1881 :UBC 0 : newedata->detail_log = pstrdup(edata->detail_log);
3453 rhaas@postgresql.org 1882 [ - + ]:CBC 3 : if (edata->hint)
3453 rhaas@postgresql.org 1883 :UBC 0 : newedata->hint = pstrdup(edata->hint);
3453 rhaas@postgresql.org 1884 [ + - ]:CBC 3 : if (edata->context)
1885 : 3 : newedata->context = pstrdup(edata->context);
1619 alvherre@alvh.no-ip. 1886 [ - + ]: 3 : if (edata->backtrace)
1619 alvherre@alvh.no-ip. 1887 :UBC 0 : newedata->backtrace = pstrdup(edata->backtrace);
1888 : : /* assume message_id is not available */
3453 rhaas@postgresql.org 1889 [ - + ]:CBC 3 : if (edata->schema_name)
3453 rhaas@postgresql.org 1890 :UBC 0 : newedata->schema_name = pstrdup(edata->schema_name);
3453 rhaas@postgresql.org 1891 [ - + ]:CBC 3 : if (edata->table_name)
3453 rhaas@postgresql.org 1892 :UBC 0 : newedata->table_name = pstrdup(edata->table_name);
3453 rhaas@postgresql.org 1893 [ - + ]:CBC 3 : if (edata->column_name)
3453 rhaas@postgresql.org 1894 :UBC 0 : newedata->column_name = pstrdup(edata->column_name);
3453 rhaas@postgresql.org 1895 [ - + ]:CBC 3 : if (edata->datatype_name)
3453 rhaas@postgresql.org 1896 :UBC 0 : newedata->datatype_name = pstrdup(edata->datatype_name);
3453 rhaas@postgresql.org 1897 [ - + ]:CBC 3 : if (edata->constraint_name)
3453 rhaas@postgresql.org 1898 :UBC 0 : newedata->constraint_name = pstrdup(edata->constraint_name);
2788 tgl@sss.pgh.pa.us 1899 :CBC 3 : newedata->cursorpos = edata->cursorpos;
1900 : 3 : newedata->internalpos = edata->internalpos;
3453 rhaas@postgresql.org 1901 [ - + ]: 3 : if (edata->internalquery)
3453 rhaas@postgresql.org 1902 :UBC 0 : newedata->internalquery = pstrdup(edata->internalquery);
1903 : :
3453 rhaas@postgresql.org 1904 :CBC 3 : MemoryContextSwitchTo(oldcontext);
2788 tgl@sss.pgh.pa.us 1905 : 3 : recursion_depth--;
1906 : :
1907 : : /* Process the error. */
1482 1908 : 3 : errfinish(edata->filename, edata->lineno, edata->funcname);
1909 : : }
1910 : :
1911 : : /*
1912 : : * ReThrowError --- re-throw a previously copied error
1913 : : *
1914 : : * A handler can do CopyErrorData/FlushErrorState to get out of the error
1915 : : * subsystem, then do some processing, and finally ReThrowError to re-throw
1916 : : * the original error. This is slower than just PG_RE_THROW() but should
1917 : : * be used if the "some processing" is likely to incur another error.
1918 : : */
1919 : : void
7197 1920 : 32 : ReThrowError(ErrorData *edata)
1921 : : {
1922 : : ErrorData *newedata;
1923 : :
1924 [ - + ]: 32 : Assert(edata->elevel == ERROR);
1925 : :
1926 : : /* Push the data back into the error context */
1927 : 32 : recursion_depth++;
1928 : 32 : MemoryContextSwitchTo(ErrorContext);
1929 : :
494 1930 : 32 : newedata = get_error_stack_entry();
7197 1931 : 32 : memcpy(newedata, edata, sizeof(ErrorData));
1932 : :
1933 : : /* Make copies of separately-allocated fields */
1934 [ + - ]: 32 : if (newedata->message)
1935 : 32 : newedata->message = pstrdup(newedata->message);
1936 [ + + ]: 32 : if (newedata->detail)
1937 : 19 : newedata->detail = pstrdup(newedata->detail);
5865 1938 [ - + ]: 32 : if (newedata->detail_log)
5865 tgl@sss.pgh.pa.us 1939 :UBC 0 : newedata->detail_log = pstrdup(newedata->detail_log);
7197 tgl@sss.pgh.pa.us 1940 [ - + ]:CBC 32 : if (newedata->hint)
7197 tgl@sss.pgh.pa.us 1941 :UBC 0 : newedata->hint = pstrdup(newedata->hint);
7197 tgl@sss.pgh.pa.us 1942 [ + + ]:CBC 32 : if (newedata->context)
1943 : 30 : newedata->context = pstrdup(newedata->context);
1619 alvherre@alvh.no-ip. 1944 [ - + ]: 32 : if (newedata->backtrace)
1619 alvherre@alvh.no-ip. 1945 :UBC 0 : newedata->backtrace = pstrdup(newedata->backtrace);
4093 tgl@sss.pgh.pa.us 1946 [ + + ]:CBC 32 : if (newedata->schema_name)
1947 : 7 : newedata->schema_name = pstrdup(newedata->schema_name);
1948 [ + + ]: 32 : if (newedata->table_name)
1949 : 7 : newedata->table_name = pstrdup(newedata->table_name);
1950 [ - + ]: 32 : if (newedata->column_name)
4093 tgl@sss.pgh.pa.us 1951 :UBC 0 : newedata->column_name = pstrdup(newedata->column_name);
4093 tgl@sss.pgh.pa.us 1952 [ - + ]:CBC 32 : if (newedata->datatype_name)
4093 tgl@sss.pgh.pa.us 1953 :UBC 0 : newedata->datatype_name = pstrdup(newedata->datatype_name);
4093 tgl@sss.pgh.pa.us 1954 [ + + ]:CBC 32 : if (newedata->constraint_name)
1955 : 7 : newedata->constraint_name = pstrdup(newedata->constraint_name);
7197 1956 [ - + ]: 32 : if (newedata->internalquery)
7197 tgl@sss.pgh.pa.us 1957 :UBC 0 : newedata->internalquery = pstrdup(newedata->internalquery);
1958 : :
1959 : : /* Reset the assoc_context to be ErrorContext */
3909 sfrost@snowman.net 1960 :CBC 32 : newedata->assoc_context = ErrorContext;
1961 : :
7197 tgl@sss.pgh.pa.us 1962 : 32 : recursion_depth--;
1963 : 32 : PG_RE_THROW();
1964 : : }
1965 : :
1966 : : /*
1967 : : * pg_re_throw --- out-of-line implementation of PG_RE_THROW() macro
1968 : : */
1969 : : void
6192 1970 : 50917 : pg_re_throw(void)
1971 : : {
1972 : : /* If possible, throw the error to the next outer setjmp handler */
1973 [ + - ]: 50917 : if (PG_exception_stack != NULL)
1974 : 50917 : siglongjmp(*PG_exception_stack, 1);
1975 : : else
1976 : : {
1977 : : /*
1978 : : * If we get here, elog(ERROR) was thrown inside a PG_TRY block, which
1979 : : * we have now exited only to discover that there is no outer setjmp
1980 : : * handler to pass the error to. Had the error been thrown outside
1981 : : * the block to begin with, we'd have promoted the error to FATAL, so
1982 : : * the correct behavior is to make it FATAL now; that is, emit it and
1983 : : * then call proc_exit.
1984 : : */
6192 tgl@sss.pgh.pa.us 1985 :UBC 0 : ErrorData *edata = &errordata[errordata_stack_depth];
1986 : :
1987 [ # # ]: 0 : Assert(errordata_stack_depth >= 0);
1988 [ # # ]: 0 : Assert(edata->elevel == ERROR);
1989 : 0 : edata->elevel = FATAL;
1990 : :
1991 : : /*
1992 : : * At least in principle, the increase in severity could have changed
1993 : : * where-to-output decisions, so recalculate.
1994 : : */
1238 1995 : 0 : edata->output_to_server = should_output_to_server(FATAL);
1996 : 0 : edata->output_to_client = should_output_to_client(FATAL);
1997 : :
1998 : : /*
1999 : : * We can use errfinish() for the rest, but we don't want it to call
2000 : : * any error context routines a second time. Since we know we are
2001 : : * about to exit, it should be OK to just clear the context stack.
2002 : : */
6192 2003 : 0 : error_context_stack = NULL;
2004 : :
1482 2005 : 0 : errfinish(edata->filename, edata->lineno, edata->funcname);
2006 : : }
2007 : :
2008 : : /* Doesn't return ... */
552 2009 : 0 : ExceptionalCondition("pg_re_throw tried to return", __FILE__, __LINE__);
2010 : : }
2011 : :
2012 : :
2013 : : /*
2014 : : * GetErrorContextStack - Return the context stack, for display/diags
2015 : : *
2016 : : * Returns a pstrdup'd string in the caller's context which includes the PG
2017 : : * error call stack. It is the caller's responsibility to ensure this string
2018 : : * is pfree'd (or its context cleaned up) when done.
2019 : : *
2020 : : * This information is collected by traversing the error contexts and calling
2021 : : * each context's callback function, each of which is expected to call
2022 : : * errcontext() to return a string which can be presented to the user.
2023 : : */
2024 : : char *
3917 sfrost@snowman.net 2025 :CBC 24 : GetErrorContextStack(void)
2026 : : {
2027 : : ErrorData *edata;
2028 : : ErrorContextCallback *econtext;
2029 : :
2030 : : /*
2031 : : * Crank up a stack entry to store the info in.
2032 : : */
3909 2033 : 24 : recursion_depth++;
2034 : :
494 tgl@sss.pgh.pa.us 2035 : 24 : edata = get_error_stack_entry();
2036 : :
2037 : : /*
2038 : : * Set up assoc_context to be the caller's context, so any allocations
2039 : : * done (which will include edata->context) will use their context.
2040 : : */
3909 sfrost@snowman.net 2041 : 24 : edata->assoc_context = CurrentMemoryContext;
2042 : :
2043 : : /*
2044 : : * Call any context callback functions to collect the context information
2045 : : * into edata->context.
2046 : : *
2047 : : * Errors occurring in callback functions should go through the regular
2048 : : * error handling code which should handle any recursive errors, though we
2049 : : * double-check above, just in case.
2050 : : */
3917 2051 : 24 : for (econtext = error_context_stack;
2052 [ + + ]: 96 : econtext != NULL;
2053 : 72 : econtext = econtext->previous)
2411 peter_e@gmx.net 2054 : 72 : econtext->callback(econtext->arg);
2055 : :
2056 : : /*
2057 : : * Clean ourselves off the stack, any allocations done should have been
2058 : : * using edata->assoc_context, which we set up earlier to be the caller's
2059 : : * context, so we're free to just remove our entry off the stack and
2060 : : * decrement recursion depth and exit.
2061 : : */
3909 sfrost@snowman.net 2062 : 24 : errordata_stack_depth--;
2063 : 24 : recursion_depth--;
2064 : :
2065 : : /*
2066 : : * Return a pointer to the string the caller asked for, which should have
2067 : : * been allocated in their context.
2068 : : */
2069 : 24 : return edata->context;
2070 : : }
2071 : :
2072 : :
2073 : : /*
2074 : : * Initialization of error output file
2075 : : */
2076 : : void
10017 bruce@momjian.us 2077 : 19656 : DebugFileOpen(void)
2078 : : {
2079 : : int fd,
2080 : : istty;
2081 : :
9716 2082 [ - + ]: 19656 : if (OutputFileName[0])
2083 : : {
2084 : : /*
2085 : : * A debug-output file name was given.
2086 : : *
2087 : : * Make sure we can write the file, and find out if it's a tty.
2088 : : */
9716 bruce@momjian.us 2089 [ # # ]:UBC 0 : if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY,
2090 : : 0666)) < 0)
7661 tgl@sss.pgh.pa.us 2091 [ # # ]: 0 : ereport(FATAL,
2092 : : (errcode_for_file_access(),
2093 : : errmsg("could not open file \"%s\": %m", OutputFileName)));
9716 bruce@momjian.us 2094 : 0 : istty = isatty(fd);
2095 : 0 : close(fd);
2096 : :
2097 : : /*
2098 : : * Redirect our stderr to the debug output file.
2099 : : */
8541 tgl@sss.pgh.pa.us 2100 [ # # ]: 0 : if (!freopen(OutputFileName, "a", stderr))
7661 2101 [ # # ]: 0 : ereport(FATAL,
2102 : : (errcode_for_file_access(),
2103 : : errmsg("could not reopen file \"%s\" as stderr: %m",
2104 : : OutputFileName)));
2105 : :
2106 : : /*
2107 : : * If the file is a tty and we're running under the postmaster, try to
2108 : : * send stdout there as well (if it isn't a tty then stderr will block
2109 : : * out stdout, so we may as well let stdout go wherever it was going
2110 : : * before).
2111 : : */
8541 2112 [ # # # # ]: 0 : if (istty && IsUnderPostmaster)
2113 [ # # ]: 0 : if (!freopen(OutputFileName, "a", stdout))
7661 2114 [ # # ]: 0 : ereport(FATAL,
2115 : : (errcode_for_file_access(),
2116 : : errmsg("could not reopen file \"%s\" as stdout: %m",
2117 : : OutputFileName)));
2118 : : }
8715 peter_e@gmx.net 2119 :CBC 19656 : }
2120 : :
2121 : :
2122 : : /*
2123 : : * GUC check_hook for backtrace_functions
2124 : : *
2125 : : * We split the input string, where commas separate function names
2126 : : * and certain whitespace chars are ignored, into a \0-separated (and
2127 : : * \0\0-terminated) list of function names. This formulation allows
2128 : : * easy scanning when an error is thrown while avoiding the use of
2129 : : * non-reentrant strtok(), as well as keeping the output data in a
2130 : : * single palloc() chunk.
2131 : : */
2132 : : bool
579 tgl@sss.pgh.pa.us 2133 : 928 : check_backtrace_functions(char **newval, void **extra, GucSource source)
2134 : : {
2135 : 928 : int newvallen = strlen(*newval);
2136 : : char *someval;
2137 : : int validlen;
2138 : : int i;
2139 : : int j;
2140 : :
2141 : : /*
2142 : : * Allow characters that can be C identifiers and commas as separators, as
2143 : : * well as some whitespace for readability.
2144 : : */
2145 : 928 : validlen = strspn(*newval,
2146 : : "0123456789_"
2147 : : "abcdefghijklmnopqrstuvwxyz"
2148 : : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2149 : : ", \n\t");
2150 [ - + ]: 928 : if (validlen != newvallen)
2151 : : {
87 peter@eisentraut.org 2152 :UNC 0 : GUC_check_errdetail("Invalid character");
579 tgl@sss.pgh.pa.us 2153 :UBC 0 : return false;
2154 : : }
2155 : :
579 tgl@sss.pgh.pa.us 2156 [ + - ]:CBC 928 : if (*newval[0] == '\0')
2157 : : {
2158 : 928 : *extra = NULL;
2159 : 928 : return true;
2160 : : }
2161 : :
2162 : : /*
2163 : : * Allocate space for the output and create the copy. We could discount
2164 : : * whitespace chars to save some memory, but it doesn't seem worth the
2165 : : * trouble.
2166 : : */
579 tgl@sss.pgh.pa.us 2167 :UBC 0 : someval = guc_malloc(ERROR, newvallen + 1 + 1);
2168 [ # # ]: 0 : for (i = 0, j = 0; i < newvallen; i++)
2169 : : {
2170 [ # # ]: 0 : if ((*newval)[i] == ',')
2171 : 0 : someval[j++] = '\0'; /* next item */
2172 [ # # ]: 0 : else if ((*newval)[i] == ' ' ||
2173 [ # # ]: 0 : (*newval)[i] == '\n' ||
2174 [ # # ]: 0 : (*newval)[i] == '\t')
2175 : : ; /* ignore these */
2176 : : else
2177 : 0 : someval[j++] = (*newval)[i]; /* copy anything else */
2178 : : }
2179 : :
2180 : : /* two \0s end the setting */
2181 : 0 : someval[j] = '\0';
2182 : 0 : someval[j + 1] = '\0';
2183 : :
2184 : 0 : *extra = someval;
2185 : 0 : return true;
2186 : : }
2187 : :
2188 : : /*
2189 : : * GUC assign_hook for backtrace_functions
2190 : : */
2191 : : void
579 tgl@sss.pgh.pa.us 2192 :CBC 928 : assign_backtrace_functions(const char *newval, void *extra)
2193 : : {
108 peter@eisentraut.org 2194 :GNC 928 : backtrace_function_list = (char *) extra;
579 tgl@sss.pgh.pa.us 2195 :CBC 928 : }
2196 : :
2197 : : /*
2198 : : * GUC check_hook for log_destination
2199 : : */
2200 : : bool
2201 : 929 : check_log_destination(char **newval, void **extra, GucSource source)
2202 : : {
2203 : : char *rawstring;
2204 : : List *elemlist;
2205 : : ListCell *l;
2206 : 929 : int newlogdest = 0;
2207 : : int *myextra;
2208 : :
2209 : : /* Need a modifiable copy of string */
2210 : 929 : rawstring = pstrdup(*newval);
2211 : :
2212 : : /* Parse string into list of identifiers */
2213 [ - + ]: 929 : if (!SplitIdentifierString(rawstring, ',', &elemlist))
2214 : : {
2215 : : /* syntax error in list */
579 tgl@sss.pgh.pa.us 2216 :UBC 0 : GUC_check_errdetail("List syntax is invalid.");
2217 : 0 : pfree(rawstring);
2218 : 0 : list_free(elemlist);
2219 : 0 : return false;
2220 : : }
2221 : :
579 tgl@sss.pgh.pa.us 2222 [ + - + + :CBC 1860 : foreach(l, elemlist)
+ + ]
2223 : : {
2224 : 931 : char *tok = (char *) lfirst(l);
2225 : :
2226 [ + + ]: 931 : if (pg_strcasecmp(tok, "stderr") == 0)
2227 : 929 : newlogdest |= LOG_DESTINATION_STDERR;
2228 [ + + ]: 2 : else if (pg_strcasecmp(tok, "csvlog") == 0)
2229 : 1 : newlogdest |= LOG_DESTINATION_CSVLOG;
2230 [ + - ]: 1 : else if (pg_strcasecmp(tok, "jsonlog") == 0)
2231 : 1 : newlogdest |= LOG_DESTINATION_JSONLOG;
2232 : : #ifdef HAVE_SYSLOG
579 tgl@sss.pgh.pa.us 2233 [ # # ]:UBC 0 : else if (pg_strcasecmp(tok, "syslog") == 0)
2234 : 0 : newlogdest |= LOG_DESTINATION_SYSLOG;
2235 : : #endif
2236 : : #ifdef WIN32
2237 : : else if (pg_strcasecmp(tok, "eventlog") == 0)
2238 : : newlogdest |= LOG_DESTINATION_EVENTLOG;
2239 : : #endif
2240 : : else
2241 : : {
2242 : 0 : GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
2243 : 0 : pfree(rawstring);
2244 : 0 : list_free(elemlist);
2245 : 0 : return false;
2246 : : }
2247 : : }
2248 : :
579 tgl@sss.pgh.pa.us 2249 :CBC 929 : pfree(rawstring);
2250 : 929 : list_free(elemlist);
2251 : :
2252 : 929 : myextra = (int *) guc_malloc(ERROR, sizeof(int));
2253 : 929 : *myextra = newlogdest;
2254 : 929 : *extra = (void *) myextra;
2255 : :
2256 : 929 : return true;
2257 : : }
2258 : :
2259 : : /*
2260 : : * GUC assign_hook for log_destination
2261 : : */
2262 : : void
2263 : 929 : assign_log_destination(const char *newval, void *extra)
2264 : : {
2265 : 929 : Log_destination = *((int *) extra);
2266 : 929 : }
2267 : :
2268 : : /*
2269 : : * GUC assign_hook for syslog_ident
2270 : : */
2271 : : void
2272 : 928 : assign_syslog_ident(const char *newval, void *extra)
2273 : : {
2274 : : #ifdef HAVE_SYSLOG
2275 : : /*
2276 : : * guc.c is likely to call us repeatedly with same parameters, so don't
2277 : : * thrash the syslog connection unnecessarily. Also, we do not re-open
2278 : : * the connection until needed, since this routine will get called whether
2279 : : * or not Log_destination actually mentions syslog.
2280 : : *
2281 : : * Note that we make our own copy of the ident string rather than relying
2282 : : * on guc.c's. This may be overly paranoid, but it ensures that we cannot
2283 : : * accidentally free a string that syslog is still using.
2284 : : */
2285 [ - + - - ]: 928 : if (syslog_ident == NULL || strcmp(syslog_ident, newval) != 0)
2286 : : {
6757 2287 [ - + ]: 928 : if (openlog_done)
2288 : : {
6757 tgl@sss.pgh.pa.us 2289 :UBC 0 : closelog();
2290 : 0 : openlog_done = false;
2291 : : }
668 peter@eisentraut.org 2292 :CBC 928 : free(syslog_ident);
579 tgl@sss.pgh.pa.us 2293 : 928 : syslog_ident = strdup(newval);
2294 : : /* if the strdup fails, we will cope in write_syslog() */
2295 : : }
2296 : : #endif
2297 : : /* Without syslog support, just ignore it */
2298 : 928 : }
2299 : :
2300 : : /*
2301 : : * GUC assign_hook for syslog_facility
2302 : : */
2303 : : void
2304 : 928 : assign_syslog_facility(int newval, void *extra)
2305 : : {
2306 : : #ifdef HAVE_SYSLOG
2307 : : /*
2308 : : * As above, don't thrash the syslog connection unnecessarily.
2309 : : */
2310 [ - + ]: 928 : if (syslog_facility != newval)
2311 : : {
579 tgl@sss.pgh.pa.us 2312 [ # # ]:UBC 0 : if (openlog_done)
2313 : : {
2314 : 0 : closelog();
2315 : 0 : openlog_done = false;
2316 : : }
2317 : 0 : syslog_facility = newval;
2318 : : }
2319 : : #endif
2320 : : /* Without syslog support, just ignore it */
6757 tgl@sss.pgh.pa.us 2321 :CBC 928 : }
2322 : :
2323 : : #ifdef HAVE_SYSLOG
2324 : :
2325 : : /*
2326 : : * Write a message line to syslog
2327 : : */
2328 : : static void
8719 peter_e@gmx.net 2329 :UBC 0 : write_syslog(int level, const char *line)
2330 : : {
2331 : : static unsigned long seq = 0;
2332 : :
2333 : : int len;
2334 : : const char *nlpos;
2335 : :
2336 : : /* Open syslog connection if not done yet */
2337 [ # # ]: 0 : if (!openlog_done)
2338 : : {
6757 tgl@sss.pgh.pa.us 2339 [ # # ]: 0 : openlog(syslog_ident ? syslog_ident : "postgres",
2340 : : LOG_PID | LOG_NDELAY | LOG_NOWAIT,
2341 : : syslog_facility);
8719 peter_e@gmx.net 2342 : 0 : openlog_done = true;
2343 : : }
2344 : :
2345 : : /*
2346 : : * We add a sequence number to each log message to suppress "same"
2347 : : * messages.
2348 : : */
2349 : 0 : seq++;
2350 : :
2351 : : /*
2352 : : * Our problem here is that many syslog implementations don't handle long
2353 : : * messages in an acceptable manner. While this function doesn't help that
2354 : : * fact, it does work around by splitting up messages into smaller pieces.
2355 : : *
2356 : : * We divide into multiple syslog() calls if message is too long or if the
2357 : : * message contains embedded newline(s).
2358 : : */
6757 tgl@sss.pgh.pa.us 2359 : 0 : len = strlen(line);
5759 2360 : 0 : nlpos = strchr(line, '\n');
2952 peter_e@gmx.net 2361 [ # # # # : 0 : if (syslog_split_messages && (len > PG_SYSLOG_LIMIT || nlpos != NULL))
# # ]
8719 2362 : 0 : {
8424 bruce@momjian.us 2363 : 0 : int chunk_nr = 0;
2364 : :
8719 peter_e@gmx.net 2365 [ # # ]: 0 : while (len > 0)
2366 : : {
2367 : : char buf[PG_SYSLOG_LIMIT + 1];
2368 : : int buflen;
2369 : : int i;
2370 : :
2371 : : /* if we start at a newline, move ahead one char */
8541 bruce@momjian.us 2372 [ # # ]: 0 : if (line[0] == '\n')
2373 : : {
2374 : 0 : line++;
2375 : 0 : len--;
2376 : : /* we need to recompute the next newline's position, too */
5759 tgl@sss.pgh.pa.us 2377 : 0 : nlpos = strchr(line, '\n');
8535 2378 : 0 : continue;
2379 : : }
2380 : :
2381 : : /* copy one line, or as much as will fit, to buf */
6409 2382 [ # # ]: 0 : if (nlpos != NULL)
2383 : 0 : buflen = nlpos - line;
2384 : : else
2385 : 0 : buflen = len;
2386 : 0 : buflen = Min(buflen, PG_SYSLOG_LIMIT);
2387 : 0 : memcpy(buf, line, buflen);
2388 : 0 : buf[buflen] = '\0';
2389 : :
2390 : : /* trim to multibyte letter boundary */
7661 2391 : 0 : buflen = pg_mbcliplen(buf, buflen, buflen);
8453 ishii@postgresql.org 2392 [ # # ]: 0 : if (buflen <= 0)
8424 bruce@momjian.us 2393 : 0 : return;
8719 peter_e@gmx.net 2394 : 0 : buf[buflen] = '\0';
2395 : :
2396 : : /* already word boundary? */
6757 tgl@sss.pgh.pa.us 2397 [ # # ]: 0 : if (line[buflen] != '\0' &&
2398 [ # # ]: 0 : !isspace((unsigned char) line[buflen]))
2399 : : {
2400 : : /* try to divide at word boundary */
7661 2401 : 0 : i = buflen - 1;
8533 2402 [ # # # # ]: 0 : while (i > 0 && !isspace((unsigned char) buf[i]))
8719 peter_e@gmx.net 2403 : 0 : i--;
2404 : :
7661 tgl@sss.pgh.pa.us 2405 [ # # ]: 0 : if (i > 0) /* else couldn't divide word boundary */
2406 : : {
8719 peter_e@gmx.net 2407 : 0 : buflen = i;
2408 : 0 : buf[i] = '\0';
2409 : : }
2410 : : }
2411 : :
2412 : 0 : chunk_nr++;
2413 : :
2970 2414 [ # # ]: 0 : if (syslog_sequence_numbers)
2415 : 0 : syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf);
2416 : : else
2417 : 0 : syslog(level, "[%d] %s", chunk_nr, buf);
2418 : :
8719 2419 : 0 : line += buflen;
2420 : 0 : len -= buflen;
2421 : : }
2422 : : }
2423 : : else
2424 : : {
2425 : : /* message short enough */
2970 2426 [ # # ]: 0 : if (syslog_sequence_numbers)
2427 : 0 : syslog(level, "[%lu] %s", seq, line);
2428 : : else
2429 : 0 : syslog(level, "%s", line);
2430 : : }
2431 : : }
2432 : : #endif /* HAVE_SYSLOG */
2433 : :
2434 : : #ifdef WIN32
2435 : : /*
2436 : : * Get the PostgreSQL equivalent of the Windows ANSI code page. "ANSI" system
2437 : : * interfaces (e.g. CreateFileA()) expect string arguments in this encoding.
2438 : : * Every process in a given system will find the same value at all times.
2439 : : */
2440 : : static int
2441 : : GetACPEncoding(void)
2442 : : {
2443 : : static int encoding = -2;
2444 : :
2445 : : if (encoding == -2)
2446 : : encoding = pg_codepage_to_encoding(GetACP());
2447 : :
2448 : : return encoding;
2449 : : }
2450 : :
2451 : : /*
2452 : : * Write a message line to the windows event log
2453 : : */
2454 : : static void
2455 : : write_eventlog(int level, const char *line, int len)
2456 : : {
2457 : : WCHAR *utf16;
2458 : : int eventlevel = EVENTLOG_ERROR_TYPE;
2459 : : static HANDLE evtHandle = INVALID_HANDLE_VALUE;
2460 : :
2461 : : if (evtHandle == INVALID_HANDLE_VALUE)
2462 : : {
2463 : : evtHandle = RegisterEventSource(NULL,
2464 : : event_source ? event_source : DEFAULT_EVENT_SOURCE);
2465 : : if (evtHandle == NULL)
2466 : : {
2467 : : evtHandle = INVALID_HANDLE_VALUE;
2468 : : return;
2469 : : }
2470 : : }
2471 : :
2472 : : switch (level)
2473 : : {
2474 : : case DEBUG5:
2475 : : case DEBUG4:
2476 : : case DEBUG3:
2477 : : case DEBUG2:
2478 : : case DEBUG1:
2479 : : case LOG:
2480 : : case LOG_SERVER_ONLY:
2481 : : case INFO:
2482 : : case NOTICE:
2483 : : eventlevel = EVENTLOG_INFORMATION_TYPE;
2484 : : break;
2485 : : case WARNING:
2486 : : case WARNING_CLIENT_ONLY:
2487 : : eventlevel = EVENTLOG_WARNING_TYPE;
2488 : : break;
2489 : : case ERROR:
2490 : : case FATAL:
2491 : : case PANIC:
2492 : : default:
2493 : : eventlevel = EVENTLOG_ERROR_TYPE;
2494 : : break;
2495 : : }
2496 : :
2497 : : /*
2498 : : * If message character encoding matches the encoding expected by
2499 : : * ReportEventA(), call it to avoid the hazards of conversion. Otherwise,
2500 : : * try to convert the message to UTF16 and write it with ReportEventW().
2501 : : * Fall back on ReportEventA() if conversion failed.
2502 : : *
2503 : : * Since we palloc the structure required for conversion, also fall
2504 : : * through to writing unconverted if we have not yet set up
2505 : : * CurrentMemoryContext.
2506 : : *
2507 : : * Also verify that we are not on our way into error recursion trouble due
2508 : : * to error messages thrown deep inside pgwin32_message_to_UTF16().
2509 : : */
2510 : : if (!in_error_recursion_trouble() &&
2511 : : CurrentMemoryContext != NULL &&
2512 : : GetMessageEncoding() != GetACPEncoding())
2513 : : {
2514 : : utf16 = pgwin32_message_to_UTF16(line, len, NULL);
2515 : : if (utf16)
2516 : : {
2517 : : ReportEventW(evtHandle,
2518 : : eventlevel,
2519 : : 0,
2520 : : 0, /* All events are Id 0 */
2521 : : NULL,
2522 : : 1,
2523 : : 0,
2524 : : (LPCWSTR *) &utf16,
2525 : : NULL);
2526 : : /* XXX Try ReportEventA() when ReportEventW() fails? */
2527 : :
2528 : : pfree(utf16);
2529 : : return;
2530 : : }
2531 : : }
2532 : : ReportEventA(evtHandle,
2533 : : eventlevel,
2534 : : 0,
2535 : : 0, /* All events are Id 0 */
2536 : : NULL,
2537 : : 1,
2538 : : 0,
2539 : : &line,
2540 : : NULL);
2541 : : }
2542 : : #endif /* WIN32 */
2543 : :
2544 : : static void
5293 magnus@hagander.net 2545 :CBC 438103 : write_console(const char *line, int len)
2546 : : {
2547 : : int rc;
2548 : :
2549 : : #ifdef WIN32
2550 : :
2551 : : /*
2552 : : * Try to convert the message to UTF16 and write it with WriteConsoleW().
2553 : : * Fall back on write() if anything fails.
2554 : : *
2555 : : * In contrast to write_eventlog(), don't skip straight to write() based
2556 : : * on the applicable encodings. Unlike WriteConsoleW(), write() depends
2557 : : * on the suitability of the console output code page. Since we put
2558 : : * stderr into binary mode in SubPostmasterMain(), write() skips the
2559 : : * necessary translation anyway.
2560 : : *
2561 : : * WriteConsoleW() will fail if stderr is redirected, so just fall through
2562 : : * to writing unconverted to the logfile in this case.
2563 : : *
2564 : : * Since we palloc the structure required for conversion, also fall
2565 : : * through to writing unconverted if we have not yet set up
2566 : : * CurrentMemoryContext.
2567 : : */
2568 : : if (!in_error_recursion_trouble() &&
2569 : : !redirection_done &&
2570 : : CurrentMemoryContext != NULL)
2571 : : {
2572 : : WCHAR *utf16;
2573 : : int utf16len;
2574 : :
2575 : : utf16 = pgwin32_message_to_UTF16(line, len, &utf16len);
2576 : : if (utf16 != NULL)
2577 : : {
2578 : : HANDLE stdHandle;
2579 : : DWORD written;
2580 : :
2581 : : stdHandle = GetStdHandle(STD_ERROR_HANDLE);
2582 : : if (WriteConsoleW(stdHandle, utf16, utf16len, &written, NULL))
2583 : : {
2584 : : pfree(utf16);
2585 : : return;
2586 : : }
2587 : :
2588 : : /*
2589 : : * In case WriteConsoleW() failed, fall back to writing the
2590 : : * message unconverted.
2591 : : */
2592 : : pfree(utf16);
2593 : : }
2594 : : }
2595 : : #else
2596 : :
2597 : : /*
2598 : : * Conversion on non-win32 platforms is not implemented yet. It requires
2599 : : * non-throw version of pg_do_encoding_conversion(), that converts
2600 : : * unconvertible characters to '?' without errors.
2601 : : *
2602 : : * XXX: We have a no-throw version now. It doesn't convert to '?' though.
2603 : : */
2604 : : #endif
2605 : :
2606 : : /*
2607 : : * We ignore any error from write() here. We have no useful way to report
2608 : : * it ... certainly whining on stderr isn't likely to be productive.
2609 : : */
4562 tgl@sss.pgh.pa.us 2610 : 438103 : rc = write(fileno(stderr), line, len);
2611 : : (void) rc;
5293 magnus@hagander.net 2612 : 438103 : }
2613 : :
2614 : : /*
2615 : : * get_formatted_log_time -- compute and get the log timestamp.
2616 : : *
2617 : : * The timestamp is computed if not set yet, so as it is kept consistent
2618 : : * among all the log destinations that require it to be consistent. Note
2619 : : * that the computed timestamp is returned in a static buffer, not
2620 : : * palloc()'d.
2621 : : */
2622 : : char *
823 michael@paquier.xyz 2623 : 646945 : get_formatted_log_time(void)
2624 : : {
2625 : : pg_time_t stamp_time;
2626 : : char msbuf[13];
2627 : :
2628 : : /* leave if already computed */
2629 [ + + ]: 646945 : if (formatted_log_time[0] != '\0')
2630 : 40 : return formatted_log_time;
2631 : :
3142 jdavis@postgresql.or 2632 [ + + ]: 646905 : if (!saved_timeval_set)
2633 : : {
2634 : 438123 : gettimeofday(&saved_timeval, NULL);
2635 : 438123 : saved_timeval_set = true;
2636 : : }
2637 : :
2638 : 646905 : stamp_time = (pg_time_t) saved_timeval.tv_sec;
2639 : :
2640 : : /*
2641 : : * Note: we expect that guc.c will ensure that log_timezone is set up (at
2642 : : * least with a minimal GMT value) before Log_line_prefix can become
2643 : : * nonempty or CSV/JSON mode can be selected.
2644 : : */
5658 alvherre@alvh.no-ip. 2645 : 646905 : pg_strftime(formatted_log_time, FORMATTED_TS_LEN,
2646 : : /* leave room for milliseconds... */
2647 : : "%Y-%m-%d %H:%M:%S %Z",
4601 tgl@sss.pgh.pa.us 2648 : 646905 : pg_localtime(&stamp_time, log_timezone));
2649 : :
2650 : : /* 'paste' milliseconds into place... */
3142 jdavis@postgresql.or 2651 : 646905 : sprintf(msbuf, ".%03d", (int) (saved_timeval.tv_usec / 1000));
3368 tgl@sss.pgh.pa.us 2652 : 646905 : memcpy(formatted_log_time + 19, msbuf, 4);
2653 : :
823 michael@paquier.xyz 2654 : 646905 : return formatted_log_time;
2655 : : }
2656 : :
2657 : : /*
2658 : : * reset_formatted_start_time -- reset the start timestamp
2659 : : */
2660 : : void
2661 : 14130 : reset_formatted_start_time(void)
2662 : : {
2663 : 14130 : formatted_start_time[0] = '\0';
2664 : 14130 : }
2665 : :
2666 : : /*
2667 : : * get_formatted_start_time -- compute and get the start timestamp.
2668 : : *
2669 : : * The timestamp is computed if not set yet. Note that the computed
2670 : : * timestamp is returned in a static buffer, not palloc()'d.
2671 : : */
2672 : : char *
2673 : 40 : get_formatted_start_time(void)
2674 : : {
5658 alvherre@alvh.no-ip. 2675 : 40 : pg_time_t stamp_time = (pg_time_t) MyStartTime;
2676 : :
2677 : : /* leave if already computed */
823 michael@paquier.xyz 2678 [ + + ]: 40 : if (formatted_start_time[0] != '\0')
2679 : 18 : return formatted_start_time;
2680 : :
2681 : : /*
2682 : : * Note: we expect that guc.c will ensure that log_timezone is set up (at
2683 : : * least with a minimal GMT value) before Log_line_prefix can become
2684 : : * nonempty or CSV/JSON mode can be selected.
2685 : : */
5658 alvherre@alvh.no-ip. 2686 : 22 : pg_strftime(formatted_start_time, FORMATTED_TS_LEN,
2687 : : "%Y-%m-%d %H:%M:%S %Z",
4601 tgl@sss.pgh.pa.us 2688 : 22 : pg_localtime(&stamp_time, log_timezone));
2689 : :
823 michael@paquier.xyz 2690 : 22 : return formatted_start_time;
2691 : : }
2692 : :
2693 : : /*
2694 : : * check_log_of_query -- check if a query can be logged
2695 : : */
2696 : : bool
2697 : 438163 : check_log_of_query(ErrorData *edata)
2698 : : {
2699 : : /* log required? */
2700 [ + + ]: 438163 : if (!is_log_level_output(edata->elevel, log_min_error_statement))
2701 : 147172 : return false;
2702 : :
2703 : : /* query log wanted? */
2704 [ + + ]: 290991 : if (edata->hide_stmt)
2705 : 175126 : return false;
2706 : :
2707 : : /* query string available? */
2708 [ + + ]: 115865 : if (debug_query_string == NULL)
2709 : 89836 : return false;
2710 : :
2711 : 26029 : return true;
2712 : : }
2713 : :
2714 : : /*
2715 : : * get_backend_type_for_log -- backend type for log entries
2716 : : *
2717 : : * Returns a pointer to a static buffer, not palloc()'d.
2718 : : */
2719 : : const char *
2720 : 23290 : get_backend_type_for_log(void)
2721 : : {
2722 : : const char *backend_type_str;
2723 : :
2724 [ + + ]: 23290 : if (MyProcPid == PostmasterPid)
2725 : 620 : backend_type_str = "postmaster";
2726 [ + + ]: 22670 : else if (MyBackendType == B_BG_WORKER)
2727 : 31 : backend_type_str = MyBgworkerEntry->bgw_type;
2728 : : else
2729 : 22639 : backend_type_str = GetBackendTypeDesc(MyBackendType);
2730 : :
2731 : 23290 : return backend_type_str;
2732 : : }
2733 : :
2734 : : /*
2735 : : * process_log_prefix_padding --- helper function for processing the format
2736 : : * string in log_line_prefix
2737 : : *
2738 : : * Note: This function returns NULL if it finds something which
2739 : : * it deems invalid in the format string.
2740 : : */
2741 : : static const char *
3853 rhaas@postgresql.org 2742 :UBC 0 : process_log_prefix_padding(const char *p, int *ppadding)
2743 : : {
3631 bruce@momjian.us 2744 : 0 : int paddingsign = 1;
2745 : 0 : int padding = 0;
2746 : :
3853 rhaas@postgresql.org 2747 [ # # ]: 0 : if (*p == '-')
2748 : : {
2749 : 0 : p++;
2750 : :
3631 bruce@momjian.us 2751 [ # # ]: 0 : if (*p == '\0') /* Did the buf end in %- ? */
3853 rhaas@postgresql.org 2752 : 0 : return NULL;
2753 : 0 : paddingsign = -1;
2754 : : }
2755 : :
2756 : : /* generate an int version of the numerical string */
2757 [ # # # # ]: 0 : while (*p >= '0' && *p <= '9')
2758 : 0 : padding = padding * 10 + (*p++ - '0');
2759 : :
2760 : : /* format is invalid if it ends with the padding number */
2761 [ # # ]: 0 : if (*p == '\0')
2762 : 0 : return NULL;
2763 : :
2764 : 0 : padding *= paddingsign;
2765 : 0 : *ppadding = padding;
2766 : 0 : return p;
2767 : : }
2768 : :
2769 : : /*
2770 : : * Format log status information using Log_line_prefix.
2771 : : */
2772 : : static void
5399 peter_e@gmx.net 2773 :CBC 646905 : log_line_prefix(StringInfo buf, ErrorData *edata)
2774 : : {
643 jdavis@postgresql.or 2775 : 646905 : log_status_format(buf, Log_line_prefix, edata);
2776 : 646905 : }
2777 : :
2778 : : /*
2779 : : * Format log status info; append to the provided buffer.
2780 : : */
2781 : : void
2782 : 646905 : log_status_format(StringInfo buf, const char *format, ErrorData *edata)
2783 : : {
2784 : : /* static counter for line numbers */
2785 : : static long log_line_number = 0;
2786 : :
2787 : : /* has counter been reset in current process? */
2788 : : static int log_my_pid = 0;
2789 : : int padding;
2790 : : const char *p;
2791 : :
2792 : : /*
2793 : : * This is one of the few places where we'd rather not inherit a static
2794 : : * variable's value from the postmaster. But since we will, reset it when
2795 : : * MyProcPid changes. MyStartTime also changes when MyProcPid does, so
2796 : : * reset the formatted start timestamp too.
2797 : : */
7331 tgl@sss.pgh.pa.us 2798 [ + + ]: 646905 : if (log_my_pid != MyProcPid)
2799 : : {
2800 : 14108 : log_line_number = 0;
2801 : 14108 : log_my_pid = MyProcPid;
823 michael@paquier.xyz 2802 : 14108 : reset_formatted_start_time();
2803 : : }
7331 tgl@sss.pgh.pa.us 2804 : 646905 : log_line_number++;
2805 : :
643 jdavis@postgresql.or 2806 [ - + ]: 646905 : if (format == NULL)
7331 tgl@sss.pgh.pa.us 2807 :UBC 0 : return; /* in case guc hasn't run yet */
2808 : :
643 jdavis@postgresql.or 2809 [ + + ]:CBC 5696622 : for (p = format; *p != '\0'; p++)
2810 : : {
3853 rhaas@postgresql.org 2811 [ + + ]: 5314791 : if (*p != '%')
2812 : : {
2813 : : /* literal char, just copy */
2814 : 2969299 : appendStringInfoChar(buf, *p);
7331 tgl@sss.pgh.pa.us 2815 : 2969299 : continue;
2816 : : }
2817 : :
2818 : : /* must be a '%', so skip to the next char */
3853 rhaas@postgresql.org 2819 : 2345492 : p++;
2820 [ - + ]: 2345492 : if (*p == '\0')
6883 tgl@sss.pgh.pa.us 2821 :UBC 0 : break; /* format error - ignore it */
3853 rhaas@postgresql.org 2822 [ - + ]:CBC 2345492 : else if (*p == '%')
2823 : : {
2824 : : /* string contains %% */
3853 rhaas@postgresql.org 2825 :UBC 0 : appendStringInfoChar(buf, '%');
2826 : 0 : continue;
2827 : : }
2828 : :
2829 : :
2830 : : /*
2831 : : * Process any formatting which may exist after the '%'. Note that
2832 : : * process_log_prefix_padding moves p past the padding number if it
2833 : : * exists.
2834 : : *
2835 : : * Note: Since only '-', '0' to '9' are valid formatting characters we
2836 : : * can do a quick check here to pre-check for formatting. If the char
2837 : : * is not formatting then we can skip a useless function call.
2838 : : *
2839 : : * Further note: At least on some platforms, passing %*s rather than
2840 : : * %s to appendStringInfo() is substantially slower, so many of the
2841 : : * cases below avoid doing that unless non-zero padding is in fact
2842 : : * specified.
2843 : : */
3853 rhaas@postgresql.org 2844 [ + - ]:CBC 2345492 : if (*p > '9')
2845 : 2345492 : padding = 0;
3853 rhaas@postgresql.org 2846 [ # # ]:UBC 0 : else if ((p = process_log_prefix_padding(p, &padding)) == NULL)
2847 : 0 : break;
2848 : :
2849 : : /* process the option */
3853 rhaas@postgresql.org 2850 [ + + - - :CBC 2345492 : switch (*p)
- + - - +
- - - - -
- + - - -
- - ]
2851 : : {
5251 tgl@sss.pgh.pa.us 2852 : 381679 : case 'a':
2853 [ + - ]: 381679 : if (MyProcPort)
2854 : : {
2855 : 381679 : const char *appname = application_name;
2856 : :
2857 [ + - + + ]: 381679 : if (appname == NULL || *appname == '\0')
2858 : 2859 : appname = _("[unknown]");
3853 rhaas@postgresql.org 2859 [ - + ]: 381679 : if (padding != 0)
3853 rhaas@postgresql.org 2860 :UBC 0 : appendStringInfo(buf, "%*s", padding, appname);
2861 : : else
3853 rhaas@postgresql.org 2862 :CBC 381679 : appendStringInfoString(buf, appname);
2863 : : }
3853 rhaas@postgresql.org 2864 [ # # ]:UBC 0 : else if (padding != 0)
2865 : 0 : appendStringInfoSpaces(buf,
2866 : : padding > 0 ? padding : -padding);
2867 : :
5251 tgl@sss.pgh.pa.us 2868 :CBC 381679 : break;
1491 peter@eisentraut.org 2869 : 23250 : case 'b':
2870 : : {
823 michael@paquier.xyz 2871 : 23250 : const char *backend_type_str = get_backend_type_for_log();
2872 : :
1491 peter@eisentraut.org 2873 [ - + ]: 23250 : if (padding != 0)
1491 peter@eisentraut.org 2874 :UBC 0 : appendStringInfo(buf, "%*s", padding, backend_type_str);
2875 : : else
1491 peter@eisentraut.org 2876 :CBC 23250 : appendStringInfoString(buf, backend_type_str);
2877 : 23250 : break;
2878 : : }
7331 tgl@sss.pgh.pa.us 2879 :UBC 0 : case 'u':
2880 [ # # ]: 0 : if (MyProcPort)
2881 : : {
2882 : 0 : const char *username = MyProcPort->user_name;
2883 : :
2884 [ # # # # ]: 0 : if (username == NULL || *username == '\0')
6991 bruce@momjian.us 2885 : 0 : username = _("[unknown]");
3853 rhaas@postgresql.org 2886 [ # # ]: 0 : if (padding != 0)
2887 : 0 : appendStringInfo(buf, "%*s", padding, username);
2888 : : else
2889 : 0 : appendStringInfoString(buf, username);
2890 : : }
2891 [ # # ]: 0 : else if (padding != 0)
2892 : 0 : appendStringInfoSpaces(buf,
2893 : : padding > 0 ? padding : -padding);
7331 tgl@sss.pgh.pa.us 2894 : 0 : break;
7168 bruce@momjian.us 2895 : 0 : case 'd':
7331 tgl@sss.pgh.pa.us 2896 [ # # ]: 0 : if (MyProcPort)
2897 : : {
2898 : 0 : const char *dbname = MyProcPort->database_name;
2899 : :
2900 [ # # # # ]: 0 : if (dbname == NULL || *dbname == '\0')
6991 bruce@momjian.us 2901 : 0 : dbname = _("[unknown]");
3853 rhaas@postgresql.org 2902 [ # # ]: 0 : if (padding != 0)
2903 : 0 : appendStringInfo(buf, "%*s", padding, dbname);
2904 : : else
2905 : 0 : appendStringInfoString(buf, dbname);
2906 : : }
2907 [ # # ]: 0 : else if (padding != 0)
2908 : 0 : appendStringInfoSpaces(buf,
2909 : : padding > 0 ? padding : -padding);
7331 tgl@sss.pgh.pa.us 2910 : 0 : break;
2911 : 0 : case 'c':
3853 rhaas@postgresql.org 2912 [ # # ]: 0 : if (padding != 0)
2913 : : {
2914 : : char strfbuf[128];
2915 : :
3808 peter_e@gmx.net 2916 : 0 : snprintf(strfbuf, sizeof(strfbuf) - 1, "%lx.%x",
2917 : : (long) (MyStartTime), MyProcPid);
3853 rhaas@postgresql.org 2918 : 0 : appendStringInfo(buf, "%*s", padding, strfbuf);
2919 : : }
2920 : : else
2921 : 0 : appendStringInfo(buf, "%lx.%x", (long) (MyStartTime), MyProcPid);
7331 tgl@sss.pgh.pa.us 2922 : 0 : break;
7331 tgl@sss.pgh.pa.us 2923 :CBC 646905 : case 'p':
3853 rhaas@postgresql.org 2924 [ - + ]: 646905 : if (padding != 0)
3853 rhaas@postgresql.org 2925 :UBC 0 : appendStringInfo(buf, "%*d", padding, MyProcPid);
2926 : : else
3853 rhaas@postgresql.org 2927 :CBC 646905 : appendStringInfo(buf, "%d", MyProcPid);
7331 tgl@sss.pgh.pa.us 2928 : 646905 : break;
2929 : :
1350 michael@paquier.xyz 2930 :UBC 0 : case 'P':
2931 [ # # ]: 0 : if (MyProc)
2932 : : {
2933 : 0 : PGPROC *leader = MyProc->lockGroupLeader;
2934 : :
2935 : : /*
2936 : : * Show the leader only for active parallel workers. This
2937 : : * leaves out the leader of a parallel group.
2938 : : */
2939 [ # # # # ]: 0 : if (leader == NULL || leader->pid == MyProcPid)
2940 : 0 : appendStringInfoSpaces(buf,
2941 : : padding > 0 ? padding : -padding);
2942 [ # # ]: 0 : else if (padding != 0)
2943 : 0 : appendStringInfo(buf, "%*d", padding, leader->pid);
2944 : : else
2945 : 0 : appendStringInfo(buf, "%d", leader->pid);
2946 : : }
2947 [ # # ]: 0 : else if (padding != 0)
2948 : 0 : appendStringInfoSpaces(buf,
2949 : : padding > 0 ? padding : -padding);
2950 : 0 : break;
2951 : :
7331 tgl@sss.pgh.pa.us 2952 : 0 : case 'l':
3853 rhaas@postgresql.org 2953 [ # # ]: 0 : if (padding != 0)
2954 : 0 : appendStringInfo(buf, "%*ld", padding, log_line_number);
2955 : : else
2956 : 0 : appendStringInfo(buf, "%ld", log_line_number);
7331 tgl@sss.pgh.pa.us 2957 : 0 : break;
6884 bruce@momjian.us 2958 :CBC 646905 : case 'm':
2959 : : /* force a log timestamp reset */
823 michael@paquier.xyz 2960 : 646905 : formatted_log_time[0] = '\0';
2961 : 646905 : (void) get_formatted_log_time();
2962 : :
3853 rhaas@postgresql.org 2963 [ - + ]: 646905 : if (padding != 0)
3853 rhaas@postgresql.org 2964 :UBC 0 : appendStringInfo(buf, "%*s", padding, formatted_log_time);
2965 : : else
3853 rhaas@postgresql.org 2966 :CBC 646905 : appendStringInfoString(buf, formatted_log_time);
6884 bruce@momjian.us 2967 : 646905 : break;
7331 tgl@sss.pgh.pa.us 2968 :UBC 0 : case 't':
2969 : : {
6098 2970 : 0 : pg_time_t stamp_time = (pg_time_t) time(NULL);
2971 : : char strfbuf[128];
2972 : :
2973 : 0 : pg_strftime(strfbuf, sizeof(strfbuf),
2974 : : "%Y-%m-%d %H:%M:%S %Z",
4601 2975 : 0 : pg_localtime(&stamp_time, log_timezone));
3853 rhaas@postgresql.org 2976 [ # # ]: 0 : if (padding != 0)
2977 : 0 : appendStringInfo(buf, "%*s", padding, strfbuf);
2978 : : else
2979 : 0 : appendStringInfoString(buf, strfbuf);
2980 : : }
7331 tgl@sss.pgh.pa.us 2981 : 0 : break;
3142 jdavis@postgresql.or 2982 : 0 : case 'n':
2983 : : {
2984 : : char strfbuf[128];
2985 : :
2986 [ # # ]: 0 : if (!saved_timeval_set)
2987 : : {
2988 : 0 : gettimeofday(&saved_timeval, NULL);
2989 : 0 : saved_timeval_set = true;
2990 : : }
2991 : :
2686 tgl@sss.pgh.pa.us 2992 : 0 : snprintf(strfbuf, sizeof(strfbuf), "%ld.%03d",
2993 : 0 : (long) saved_timeval.tv_sec,
2994 : 0 : (int) (saved_timeval.tv_usec / 1000));
2995 : :
3142 jdavis@postgresql.or 2996 [ # # ]: 0 : if (padding != 0)
2997 : 0 : appendStringInfo(buf, "%*s", padding, strfbuf);
2998 : : else
2999 : 0 : appendStringInfoString(buf, strfbuf);
3000 : : }
3001 : 0 : break;
7331 tgl@sss.pgh.pa.us 3002 : 0 : case 's':
3003 : : {
823 michael@paquier.xyz 3004 : 0 : char *start_time = get_formatted_start_time();
3005 : :
3006 [ # # ]: 0 : if (padding != 0)
3007 : 0 : appendStringInfo(buf, "%*s", padding, start_time);
3008 : : else
3009 : 0 : appendStringInfoString(buf, start_time);
3010 : : }
7331 tgl@sss.pgh.pa.us 3011 : 0 : break;
3012 : 0 : case 'i':
3013 [ # # ]: 0 : if (MyProcPort)
3014 : : {
3015 : : const char *psdisp;
3016 : : int displen;
3017 : :
6735 3018 : 0 : psdisp = get_ps_display(&displen);
3853 rhaas@postgresql.org 3019 [ # # ]: 0 : if (padding != 0)
3020 : 0 : appendStringInfo(buf, "%*s", padding, psdisp);
3021 : : else
3022 : 0 : appendBinaryStringInfo(buf, psdisp, displen);
3023 : : }
3024 [ # # ]: 0 : else if (padding != 0)
3025 : 0 : appendStringInfoSpaces(buf,
3026 : : padding > 0 ? padding : -padding);
7331 tgl@sss.pgh.pa.us 3027 : 0 : break;
3028 : 0 : case 'r':
6735 3029 [ # # # # ]: 0 : if (MyProcPort && MyProcPort->remote_host)
3030 : : {
3808 peter_e@gmx.net 3031 [ # # ]: 0 : if (padding != 0)
3032 : : {
3853 rhaas@postgresql.org 3033 [ # # # # ]: 0 : if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
3034 : 0 : {
3035 : : /*
3036 : : * This option is slightly special as the port
3037 : : * number may be appended onto the end. Here we
3038 : : * need to build 1 string which contains the
3039 : : * remote_host and optionally the remote_port (if
3040 : : * set) so we can properly align the string.
3041 : : */
3042 : :
3043 : : char *hostport;
3044 : :
3827 peter_e@gmx.net 3045 : 0 : hostport = psprintf("%s(%s)", MyProcPort->remote_host, MyProcPort->remote_port);
3853 rhaas@postgresql.org 3046 : 0 : appendStringInfo(buf, "%*s", padding, hostport);
3047 : 0 : pfree(hostport);
3048 : : }
3049 : : else
3050 : 0 : appendStringInfo(buf, "%*s", padding, MyProcPort->remote_host);
3051 : : }
3052 : : else
3053 : : {
3054 : : /* padding is 0, so we don't need a temp buffer */
3055 : 0 : appendStringInfoString(buf, MyProcPort->remote_host);
3056 [ # # ]: 0 : if (MyProcPort->remote_port &&
3057 [ # # ]: 0 : MyProcPort->remote_port[0] != '\0')
3808 peter_e@gmx.net 3058 : 0 : appendStringInfo(buf, "(%s)",
3631 bruce@momjian.us 3059 : 0 : MyProcPort->remote_port);
3060 : : }
3061 : : }
3853 rhaas@postgresql.org 3062 [ # # ]: 0 : else if (padding != 0)
3063 : 0 : appendStringInfoSpaces(buf,
3064 : : padding > 0 ? padding : -padding);
7331 tgl@sss.pgh.pa.us 3065 : 0 : break;
6884 bruce@momjian.us 3066 : 0 : case 'h':
3808 peter_e@gmx.net 3067 [ # # # # ]: 0 : if (MyProcPort && MyProcPort->remote_host)
3068 : : {
3853 rhaas@postgresql.org 3069 [ # # ]: 0 : if (padding != 0)
3070 : 0 : appendStringInfo(buf, "%*s", padding, MyProcPort->remote_host);
3071 : : else
3072 : 0 : appendStringInfoString(buf, MyProcPort->remote_host);
3073 : : }
3074 [ # # ]: 0 : else if (padding != 0)
3075 : 0 : appendStringInfoSpaces(buf,
3076 : : padding > 0 ? padding : -padding);
6884 bruce@momjian.us 3077 : 0 : break;
7144 neilc@samurai.com 3078 :CBC 646753 : case 'q':
3079 : : /* in postmaster and friends, stop if %q is seen */
3080 : : /* in a backend, just ignore */
7331 tgl@sss.pgh.pa.us 3081 [ + + ]: 646753 : if (MyProcPort == NULL)
3853 rhaas@postgresql.org 3082 : 265074 : return;
7331 tgl@sss.pgh.pa.us 3083 : 381679 : break;
6066 tgl@sss.pgh.pa.us 3084 :UBC 0 : case 'v':
3085 : : /* keep VXID format in sync with lockfuncs.c */
42 heikki.linnakangas@i 3086 [ # # # # ]:UNC 0 : if (MyProc != NULL && MyProc->vxid.procNumber != INVALID_PROC_NUMBER)
3087 : : {
3853 rhaas@postgresql.org 3088 [ # # ]:UBC 0 : if (padding != 0)
3089 : : {
3090 : : char strfbuf[128];
3091 : :
3092 : 0 : snprintf(strfbuf, sizeof(strfbuf) - 1, "%d/%u",
42 heikki.linnakangas@i 3093 :UNC 0 : MyProc->vxid.procNumber, MyProc->vxid.lxid);
3853 rhaas@postgresql.org 3094 :UBC 0 : appendStringInfo(buf, "%*s", padding, strfbuf);
3095 : : }
3096 : : else
42 heikki.linnakangas@i 3097 :UNC 0 : appendStringInfo(buf, "%d/%u", MyProc->vxid.procNumber, MyProc->vxid.lxid);
3098 : : }
3853 rhaas@postgresql.org 3099 [ # # ]:UBC 0 : else if (padding != 0)
3100 : 0 : appendStringInfoSpaces(buf,
3101 : : padding > 0 ? padding : -padding);
6066 tgl@sss.pgh.pa.us 3102 : 0 : break;
7144 neilc@samurai.com 3103 : 0 : case 'x':
3853 rhaas@postgresql.org 3104 [ # # ]: 0 : if (padding != 0)
3105 : 0 : appendStringInfo(buf, "%*u", padding, GetTopTransactionIdIfAny());
3106 : : else
3107 : 0 : appendStringInfo(buf, "%u", GetTopTransactionIdIfAny());
7144 neilc@samurai.com 3108 : 0 : break;
5399 peter_e@gmx.net 3109 : 0 : case 'e':
3853 rhaas@postgresql.org 3110 [ # # ]: 0 : if (padding != 0)
3111 : 0 : appendStringInfo(buf, "%*s", padding, unpack_sql_state(edata->sqlerrcode));
3112 : : else
3113 : 0 : appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode));
7331 tgl@sss.pgh.pa.us 3114 : 0 : break;
1103 bruce@momjian.us 3115 : 0 : case 'Q':
3116 [ # # ]: 0 : if (padding != 0)
3117 : 0 : appendStringInfo(buf, "%*lld", padding,
1068 tgl@sss.pgh.pa.us 3118 : 0 : (long long) pgstat_get_my_query_id());
3119 : : else
1103 bruce@momjian.us 3120 : 0 : appendStringInfo(buf, "%lld",
1068 tgl@sss.pgh.pa.us 3121 : 0 : (long long) pgstat_get_my_query_id());
1103 bruce@momjian.us 3122 : 0 : break;
7331 tgl@sss.pgh.pa.us 3123 : 0 : default:
3124 : : /* format error - ignore it */
3125 : 0 : break;
3126 : : }
3127 : : }
3128 : : }
3129 : :
3130 : : /*
3131 : : * Unpack MAKE_SQLSTATE code. Note that this returns a pointer to a
3132 : : * static buffer.
3133 : : */
3134 : : char *
6883 neilc@samurai.com 3135 :CBC 107211 : unpack_sql_state(int sql_state)
3136 : : {
3137 : : static char buf[12];
3138 : : int i;
3139 : :
3140 [ + + ]: 643266 : for (i = 0; i < 5; i++)
3141 : : {
3142 : 536055 : buf[i] = PGUNSIXBIT(sql_state);
3143 : 536055 : sql_state >>= 6;
3144 : : }
3145 : :
3146 : 107211 : buf[i] = '\0';
3147 : 107211 : return buf;
3148 : : }
3149 : :
3150 : :
3151 : : /*
3152 : : * Write error report to server's log
3153 : : */
3154 : : static void
7555 bruce@momjian.us 3155 : 438123 : send_message_to_server_log(ErrorData *edata)
3156 : : {
3157 : : StringInfoData buf;
919 michael@paquier.xyz 3158 : 438123 : bool fallback_to_stderr = false;
3159 : :
7661 tgl@sss.pgh.pa.us 3160 : 438123 : initStringInfo(&buf);
3161 : :
5399 peter_e@gmx.net 3162 : 438123 : log_line_prefix(&buf, edata);
2788 tgl@sss.pgh.pa.us 3163 : 438123 : appendStringInfo(&buf, "%s: ", _(error_severity(edata->elevel)));
3164 : :
7594 3165 [ + + ]: 438123 : if (Log_error_verbosity >= PGERROR_VERBOSE)
6883 neilc@samurai.com 3166 : 74 : appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
3167 : :
7661 tgl@sss.pgh.pa.us 3168 [ + - ]: 438123 : if (edata->message)
7485 3169 : 438123 : append_with_tabs(&buf, edata->message);
3170 : : else
6991 bruce@momjian.us 3171 :UBC 0 : append_with_tabs(&buf, _("missing error text"));
3172 : :
7594 tgl@sss.pgh.pa.us 3173 [ + + ]:CBC 438123 : if (edata->cursorpos > 0)
6991 bruce@momjian.us 3174 : 4841 : appendStringInfo(&buf, _(" at character %d"),
3175 : : edata->cursorpos);
7329 tgl@sss.pgh.pa.us 3176 [ + + ]: 433282 : else if (edata->internalpos > 0)
6991 bruce@momjian.us 3177 : 43 : appendStringInfo(&buf, _(" at character %d"),
3178 : : edata->internalpos);
3179 : :
7594 tgl@sss.pgh.pa.us 3180 : 438123 : appendStringInfoChar(&buf, '\n');
3181 : :
3182 [ + - ]: 438123 : if (Log_error_verbosity >= PGERROR_DEFAULT)
3183 : : {
5865 3184 [ + + ]: 438123 : if (edata->detail_log)
3185 : : {
5399 peter_e@gmx.net 3186 : 271 : log_line_prefix(&buf, edata);
5865 tgl@sss.pgh.pa.us 3187 : 271 : appendStringInfoString(&buf, _("DETAIL: "));
3188 : 271 : append_with_tabs(&buf, edata->detail_log);
3189 : 271 : appendStringInfoChar(&buf, '\n');
3190 : : }
3191 [ + + ]: 437852 : else if (edata->detail)
3192 : : {
5399 peter_e@gmx.net 3193 : 34214 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3194 : 34214 : appendStringInfoString(&buf, _("DETAIL: "));
7485 tgl@sss.pgh.pa.us 3195 : 34214 : append_with_tabs(&buf, edata->detail);
3196 : 34214 : appendStringInfoChar(&buf, '\n');
3197 : : }
7594 3198 [ + + ]: 438123 : if (edata->hint)
3199 : : {
5399 peter_e@gmx.net 3200 : 145397 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3201 : 145397 : appendStringInfoString(&buf, _("HINT: "));
7485 tgl@sss.pgh.pa.us 3202 : 145397 : append_with_tabs(&buf, edata->hint);
3203 : 145397 : appendStringInfoChar(&buf, '\n');
3204 : : }
7329 3205 [ + + ]: 438123 : if (edata->internalquery)
3206 : : {
5399 peter_e@gmx.net 3207 : 43 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3208 : 43 : appendStringInfoString(&buf, _("QUERY: "));
7329 tgl@sss.pgh.pa.us 3209 : 43 : append_with_tabs(&buf, edata->internalquery);
3210 : 43 : appendStringInfoChar(&buf, '\n');
3211 : : }
3398 andres@anarazel.de 3212 [ + + + - ]: 438123 : if (edata->context && !edata->hide_ctx)
3213 : : {
5399 peter_e@gmx.net 3214 : 2758 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3215 : 2758 : appendStringInfoString(&buf, _("CONTEXT: "));
7485 tgl@sss.pgh.pa.us 3216 : 2758 : append_with_tabs(&buf, edata->context);
3217 : 2758 : appendStringInfoChar(&buf, '\n');
3218 : : }
7594 3219 [ + + ]: 438123 : if (Log_error_verbosity >= PGERROR_VERBOSE)
3220 : : {
3221 : : /* assume no newlines in funcname or filename... */
3222 [ + - + - ]: 74 : if (edata->funcname && edata->filename)
3223 : : {
5399 peter_e@gmx.net 3224 : 74 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3225 : 74 : appendStringInfo(&buf, _("LOCATION: %s, %s:%d\n"),
3226 : : edata->funcname, edata->filename,
3227 : : edata->lineno);
3228 : : }
7594 tgl@sss.pgh.pa.us 3229 [ # # ]:UBC 0 : else if (edata->filename)
3230 : : {
5399 peter_e@gmx.net 3231 : 0 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3232 : 0 : appendStringInfo(&buf, _("LOCATION: %s:%d\n"),
3233 : : edata->filename, edata->lineno);
3234 : : }
3235 : : }
1374 peter@eisentraut.org 3236 [ - + ]:CBC 438123 : if (edata->backtrace)
3237 : : {
1374 peter@eisentraut.org 3238 :UBC 0 : log_line_prefix(&buf, edata);
3239 : 0 : appendStringInfoString(&buf, _("BACKTRACE: "));
3240 : 0 : append_with_tabs(&buf, edata->backtrace);
3241 : 0 : appendStringInfoChar(&buf, '\n');
3242 : : }
3243 : : }
3244 : :
3245 : : /*
3246 : : * If the user wants the query that generated this error logged, do it.
3247 : : */
823 michael@paquier.xyz 3248 [ + + ]:CBC 438123 : if (check_log_of_query(edata))
3249 : : {
5399 peter_e@gmx.net 3250 : 26025 : log_line_prefix(&buf, edata);
6991 bruce@momjian.us 3251 : 26025 : appendStringInfoString(&buf, _("STATEMENT: "));
7485 tgl@sss.pgh.pa.us 3252 : 26025 : append_with_tabs(&buf, debug_query_string);
3253 : 26025 : appendStringInfoChar(&buf, '\n');
3254 : : }
3255 : :
3256 : : #ifdef HAVE_SYSLOG
3257 : : /* Write to syslog, if enabled */
7314 bruce@momjian.us 3258 [ - + ]: 438123 : if (Log_destination & LOG_DESTINATION_SYSLOG)
3259 : : {
3260 : : int syslog_level;
3261 : :
7661 tgl@sss.pgh.pa.us 3262 [ # # # # :UBC 0 : switch (edata->elevel)
# # ]
3263 : : {
3264 : 0 : case DEBUG5:
3265 : : case DEBUG4:
3266 : : case DEBUG3:
3267 : : case DEBUG2:
3268 : : case DEBUG1:
3269 : 0 : syslog_level = LOG_DEBUG;
3270 : 0 : break;
3271 : 0 : case LOG:
3272 : : case LOG_SERVER_ONLY:
3273 : : case INFO:
3274 : 0 : syslog_level = LOG_INFO;
3275 : 0 : break;
3276 : 0 : case NOTICE:
3277 : : case WARNING:
3278 : : case WARNING_CLIENT_ONLY:
3279 : 0 : syslog_level = LOG_NOTICE;
3280 : 0 : break;
3281 : 0 : case ERROR:
3282 : 0 : syslog_level = LOG_WARNING;
3283 : 0 : break;
3284 : 0 : case FATAL:
3285 : 0 : syslog_level = LOG_ERR;
3286 : 0 : break;
3287 : 0 : case PANIC:
3288 : : default:
3289 : 0 : syslog_level = LOG_CRIT;
3290 : 0 : break;
3291 : : }
3292 : :
3293 : 0 : write_syslog(syslog_level, buf.data);
3294 : : }
3295 : : #endif /* HAVE_SYSLOG */
3296 : :
3297 : : #ifdef WIN32
3298 : : /* Write to eventlog, if enabled */
3299 : : if (Log_destination & LOG_DESTINATION_EVENTLOG)
3300 : : {
3301 : : write_eventlog(edata->elevel, buf.data, buf.len);
3302 : : }
3303 : : #endif /* WIN32 */
3304 : :
3305 : : /* Write to csvlog, if enabled */
919 michael@paquier.xyz 3306 [ + + ]:CBC 438123 : if (Log_destination & LOG_DESTINATION_CSVLOG)
3307 : : {
3308 : : /*
3309 : : * Send CSV data if it's safe to do so (syslogger doesn't need the
3310 : : * pipe). If this is not possible, fallback to an entry written to
3311 : : * stderr.
3312 : : */
3313 [ + + - + ]: 21 : if (redirection_done || MyBackendType == B_LOGGER)
3314 : 20 : write_csvlog(edata);
3315 : : else
3316 : 1 : fallback_to_stderr = true;
3317 : : }
3318 : :
3319 : : /* Write to JSON log, if enabled */
818 3320 [ + + ]: 438123 : if (Log_destination & LOG_DESTINATION_JSONLOG)
3321 : : {
3322 : : /*
3323 : : * Send JSON data if it's safe to do so (syslogger doesn't need the
3324 : : * pipe). If this is not possible, fallback to an entry written to
3325 : : * stderr.
3326 : : */
3327 [ + + - + ]: 21 : if (redirection_done || MyBackendType == B_LOGGER)
3328 : : {
3329 : 20 : write_jsonlog(edata);
3330 : : }
3331 : : else
3332 : 1 : fallback_to_stderr = true;
3333 : : }
3334 : :
3335 : : /*
3336 : : * Write to stderr, if enabled or if required because of a previous
3337 : : * limitation.
3338 : : */
919 3339 [ - + ]: 438123 : if ((Log_destination & LOG_DESTINATION_STDERR) ||
919 michael@paquier.xyz 3340 [ # # # # ]:UBC 0 : whereToSendOutput == DestDebug ||
3341 : : fallback_to_stderr)
3342 : : {
3343 : : /*
3344 : : * Use the chunking protocol if we know the syslogger should be
3345 : : * catching stderr output, and we are not ourselves the syslogger.
3346 : : * Otherwise, just do a vanilla write to stderr.
3347 : : */
1495 peter@eisentraut.org 3348 [ + + + - ]:CBC 438123 : if (redirection_done && MyBackendType != B_LOGGER)
6083 andrew@dunslane.net 3349 : 20 : write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_STDERR);
3350 : : #ifdef WIN32
3351 : :
3352 : : /*
3353 : : * In a win32 service environment, there is no usable stderr. Capture
3354 : : * anything going there and write it to the eventlog instead.
3355 : : *
3356 : : * If stderr redirection is active, it was OK to write to stderr above
3357 : : * because that's really a pipe to the syslogger process.
3358 : : */
3359 : : else if (pgwin32_is_service())
3360 : : write_eventlog(edata->elevel, buf.data, buf.len);
3361 : : #endif
3362 : : else
5293 magnus@hagander.net 3363 : 438103 : write_console(buf.data, buf.len);
3364 : : }
3365 : :
3366 : : /* If in the syslogger process, try to write messages direct to file */
1495 peter@eisentraut.org 3367 [ - + ]: 438123 : if (MyBackendType == B_LOGGER)
6079 andrew@dunslane.net 3368 :UBC 0 : write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR);
3369 : :
3370 : : /* No more need of the message formatted for stderr */
919 michael@paquier.xyz 3371 :CBC 438123 : pfree(buf.data);
7661 tgl@sss.pgh.pa.us 3372 : 438123 : }
3373 : :
3374 : : /*
3375 : : * Send data to the syslogger using the chunked protocol
3376 : : *
3377 : : * Note: when there are multiple backends writing into the syslogger pipe,
3378 : : * it's critical that each write go into the pipe indivisibly, and not
3379 : : * get interleaved with data from other processes. Fortunately, the POSIX
3380 : : * spec requires that writes to pipes be atomic so long as they are not
3381 : : * more than PIPE_BUF bytes long. So we divide long messages into chunks
3382 : : * that are no more than that length, and send one chunk per write() call.
3383 : : * The collector process knows how to reassemble the chunks.
3384 : : *
3385 : : * Because of the atomic write requirement, there are only two possible
3386 : : * results from write() here: -1 for failure, or the requested number of
3387 : : * bytes. There is not really anything we can do about a failure; retry would
3388 : : * probably be an infinite loop, and we can't even report the error usefully.
3389 : : * (There is noplace else we could send it!) So we might as well just ignore
3390 : : * the result from write(). However, on some platforms you get a compiler
3391 : : * warning from ignoring write()'s result, so do a little dance with casting
3392 : : * rc to void to shut up the compiler.
3393 : : */
3394 : : void
6083 andrew@dunslane.net 3395 : 60 : write_pipe_chunks(char *data, int len, int dest)
3396 : : {
3397 : : PipeProtoChunk p;
5995 bruce@momjian.us 3398 : 60 : int fd = fileno(stderr);
3399 : : int rc;
3400 : :
6149 andrew@dunslane.net 3401 [ - + ]: 60 : Assert(len > 0);
3402 : :
3403 : 60 : p.proto.nuls[0] = p.proto.nuls[1] = '\0';
3404 : 60 : p.proto.pid = MyProcPid;
944 michael@paquier.xyz 3405 : 60 : p.proto.flags = 0;
3406 [ + + ]: 60 : if (dest == LOG_DESTINATION_STDERR)
3407 : 20 : p.proto.flags |= PIPE_PROTO_DEST_STDERR;
3408 [ + + ]: 40 : else if (dest == LOG_DESTINATION_CSVLOG)
3409 : 20 : p.proto.flags |= PIPE_PROTO_DEST_CSVLOG;
818 3410 [ + - ]: 20 : else if (dest == LOG_DESTINATION_JSONLOG)
3411 : 20 : p.proto.flags |= PIPE_PROTO_DEST_JSONLOG;
3412 : :
3413 : : /* write all but the last chunk */
6149 andrew@dunslane.net 3414 [ - + ]: 60 : while (len > PIPE_MAX_PAYLOAD)
3415 : : {
3416 : : /* no need to set PIPE_PROTO_IS_LAST yet */
6149 andrew@dunslane.net 3417 :UBC 0 : p.proto.len = PIPE_MAX_PAYLOAD;
3418 : 0 : memcpy(p.proto.data, data, PIPE_MAX_PAYLOAD);
4562 tgl@sss.pgh.pa.us 3419 : 0 : rc = write(fd, &p, PIPE_HEADER_SIZE + PIPE_MAX_PAYLOAD);
3420 : : (void) rc;
6149 andrew@dunslane.net 3421 : 0 : data += PIPE_MAX_PAYLOAD;
3422 : 0 : len -= PIPE_MAX_PAYLOAD;
3423 : : }
3424 : :
3425 : : /* write the last chunk */
944 michael@paquier.xyz 3426 :CBC 60 : p.proto.flags |= PIPE_PROTO_IS_LAST;
6149 andrew@dunslane.net 3427 : 60 : p.proto.len = len;
3428 : 60 : memcpy(p.proto.data, data, len);
4562 tgl@sss.pgh.pa.us 3429 : 60 : rc = write(fd, &p, PIPE_HEADER_SIZE + len);
3430 : : (void) rc;
6149 andrew@dunslane.net 3431 : 60 : }
3432 : :
3433 : :
3434 : : /*
3435 : : * Append a text string to the error report being built for the client.
3436 : : *
3437 : : * This is ordinarily identical to pq_sendstring(), but if we are in
3438 : : * error recursion trouble we skip encoding conversion, because of the
3439 : : * possibility that the problem is a failure in the encoding conversion
3440 : : * subsystem itself. Code elsewhere should ensure that the passed-in
3441 : : * strings will be plain 7-bit ASCII, and thus not in need of conversion,
3442 : : * in such cases. (In particular, we disable localization of error messages
3443 : : * to help ensure that's true.)
3444 : : */
3445 : : static void
5522 tgl@sss.pgh.pa.us 3446 : 776365 : err_sendstring(StringInfo buf, const char *str)
3447 : : {
3448 [ - + ]: 776365 : if (in_error_recursion_trouble())
5522 tgl@sss.pgh.pa.us 3449 :UBC 0 : pq_send_ascii_string(buf, str);
3450 : : else
5522 tgl@sss.pgh.pa.us 3451 :CBC 776365 : pq_sendstring(buf, str);
3452 : 776365 : }
3453 : :
3454 : : /*
3455 : : * Write error report to client
3456 : : */
3457 : : static void
7555 bruce@momjian.us 3458 : 97914 : send_message_to_frontend(ErrorData *edata)
3459 : : {
3460 : : StringInfoData msgbuf;
3461 : :
3462 : : /*
3463 : : * We no longer support pre-3.0 FE/BE protocol, except here. If a client
3464 : : * tries to connect using an older protocol version, it's nice to send the
3465 : : * "protocol version not supported" error in a format the client
3466 : : * understands. If protocol hasn't been set yet, early in backend
3467 : : * startup, assume modern protocol.
3468 : : */
1137 heikki.linnakangas@i 3469 [ - + - - ]: 97914 : if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3 || FrontendProtocol == 0)
7661 tgl@sss.pgh.pa.us 3470 : 97914 : {
3471 : : /* New style with separate fields */
3472 : : const char *sev;
3473 : : char tbuf[12];
3474 : :
3475 : : /* 'N' (Notice) is for nonfatal conditions, 'E' is for errors */
236 nathan@postgresql.or 3476 [ + + ]:GNC 97914 : if (edata->elevel < ERROR)
3477 : 77585 : pq_beginmessage(&msgbuf, PqMsg_NoticeResponse);
3478 : : else
3479 : 20329 : pq_beginmessage(&msgbuf, PqMsg_ErrorResponse);
3480 : :
2788 tgl@sss.pgh.pa.us 3481 :CBC 97914 : sev = error_severity(edata->elevel);
7536 peter_e@gmx.net 3482 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
2788 tgl@sss.pgh.pa.us 3483 : 97914 : err_sendstring(&msgbuf, _(sev));
3484 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY_NONLOCALIZED);
3485 : 97914 : err_sendstring(&msgbuf, sev);
3486 : :
7536 peter_e@gmx.net 3487 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SQLSTATE);
956 michael@paquier.xyz 3488 : 97914 : err_sendstring(&msgbuf, unpack_sql_state(edata->sqlerrcode));
3489 : :
3490 : : /* M field is required per protocol, so always send something */
7536 peter_e@gmx.net 3491 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY);
7661 tgl@sss.pgh.pa.us 3492 [ + - ]: 97914 : if (edata->message)
5522 3493 : 97914 : err_sendstring(&msgbuf, edata->message);
3494 : : else
5522 tgl@sss.pgh.pa.us 3495 :UBC 0 : err_sendstring(&msgbuf, _("missing error text"));
3496 : :
7661 tgl@sss.pgh.pa.us 3497 [ + + ]:CBC 97914 : if (edata->detail)
3498 : : {
7536 peter_e@gmx.net 3499 : 4880 : pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL);
5522 tgl@sss.pgh.pa.us 3500 : 4880 : err_sendstring(&msgbuf, edata->detail);
3501 : : }
3502 : :
3503 : : /* detail_log is intentionally not used here */
3504 : :
7661 3505 [ + + ]: 97914 : if (edata->hint)
3506 : : {
7536 peter_e@gmx.net 3507 : 67126 : pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT);
5522 tgl@sss.pgh.pa.us 3508 : 67126 : err_sendstring(&msgbuf, edata->hint);
3509 : : }
3510 : :
7661 3511 [ + + ]: 97914 : if (edata->context)
3512 : : {
7536 peter_e@gmx.net 3513 : 8461 : pq_sendbyte(&msgbuf, PG_DIAG_CONTEXT);
5522 tgl@sss.pgh.pa.us 3514 : 8461 : err_sendstring(&msgbuf, edata->context);
3515 : : }
3516 : :
4093 3517 [ + + ]: 97914 : if (edata->schema_name)
3518 : : {
3519 : 1966 : pq_sendbyte(&msgbuf, PG_DIAG_SCHEMA_NAME);
3520 : 1966 : err_sendstring(&msgbuf, edata->schema_name);
3521 : : }
3522 : :
3523 [ + + ]: 97914 : if (edata->table_name)
3524 : : {
3525 : 1604 : pq_sendbyte(&msgbuf, PG_DIAG_TABLE_NAME);
3526 : 1604 : err_sendstring(&msgbuf, edata->table_name);
3527 : : }
3528 : :
3529 [ + + ]: 97914 : if (edata->column_name)
3530 : : {
3531 : 201 : pq_sendbyte(&msgbuf, PG_DIAG_COLUMN_NAME);
3532 : 201 : err_sendstring(&msgbuf, edata->column_name);
3533 : : }
3534 : :
3535 [ + + ]: 97914 : if (edata->datatype_name)
3536 : : {
3537 : 367 : pq_sendbyte(&msgbuf, PG_DIAG_DATATYPE_NAME);
3538 : 367 : err_sendstring(&msgbuf, edata->datatype_name);
3539 : : }
3540 : :
3541 [ + + ]: 97914 : if (edata->constraint_name)
3542 : : {
3543 : 1427 : pq_sendbyte(&msgbuf, PG_DIAG_CONSTRAINT_NAME);
3544 : 1427 : err_sendstring(&msgbuf, edata->constraint_name);
3545 : : }
3546 : :
7661 3547 [ + + ]: 97914 : if (edata->cursorpos > 0)
3548 : : {
3549 : 4849 : snprintf(tbuf, sizeof(tbuf), "%d", edata->cursorpos);
7536 peter_e@gmx.net 3550 : 4849 : pq_sendbyte(&msgbuf, PG_DIAG_STATEMENT_POSITION);
5522 tgl@sss.pgh.pa.us 3551 : 4849 : err_sendstring(&msgbuf, tbuf);
3552 : : }
3553 : :
7329 3554 [ + + ]: 97914 : if (edata->internalpos > 0)
3555 : : {
3556 : 43 : snprintf(tbuf, sizeof(tbuf), "%d", edata->internalpos);
3557 : 43 : pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_POSITION);
5522 3558 : 43 : err_sendstring(&msgbuf, tbuf);
3559 : : }
3560 : :
7329 3561 [ + + ]: 97914 : if (edata->internalquery)
3562 : : {
3563 : 43 : pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_QUERY);
5522 3564 : 43 : err_sendstring(&msgbuf, edata->internalquery);
3565 : : }
3566 : :
7661 3567 [ + - ]: 97914 : if (edata->filename)
3568 : : {
7536 peter_e@gmx.net 3569 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FILE);
5522 tgl@sss.pgh.pa.us 3570 : 97914 : err_sendstring(&msgbuf, edata->filename);
3571 : : }
3572 : :
7661 3573 [ + - ]: 97914 : if (edata->lineno > 0)
3574 : : {
3575 : 97914 : snprintf(tbuf, sizeof(tbuf), "%d", edata->lineno);
7536 peter_e@gmx.net 3576 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_LINE);
5522 tgl@sss.pgh.pa.us 3577 : 97914 : err_sendstring(&msgbuf, tbuf);
3578 : : }
3579 : :
7661 3580 [ + - ]: 97914 : if (edata->funcname)
3581 : : {
7536 peter_e@gmx.net 3582 : 97914 : pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FUNCTION);
5522 tgl@sss.pgh.pa.us 3583 : 97914 : err_sendstring(&msgbuf, edata->funcname);
3584 : : }
3585 : :
2489 3586 : 97914 : pq_sendbyte(&msgbuf, '\0'); /* terminator */
3587 : :
1137 heikki.linnakangas@i 3588 : 97914 : pq_endmessage(&msgbuf);
3589 : : }
3590 : : else
3591 : : {
3592 : : /* Old style --- gin up a backwards-compatible message */
3593 : : StringInfoData buf;
3594 : :
7661 tgl@sss.pgh.pa.us 3595 :UBC 0 : initStringInfo(&buf);
3596 : :
2788 3597 : 0 : appendStringInfo(&buf, "%s: ", _(error_severity(edata->elevel)));
3598 : :
7661 3599 [ # # ]: 0 : if (edata->message)
7485 3600 : 0 : appendStringInfoString(&buf, edata->message);
3601 : : else
6991 bruce@momjian.us 3602 : 0 : appendStringInfoString(&buf, _("missing error text"));
3603 : :
7661 tgl@sss.pgh.pa.us 3604 : 0 : appendStringInfoChar(&buf, '\n');
3605 : :
3606 : : /* 'N' (Notice) is for nonfatal conditions, 'E' is for errors */
1137 heikki.linnakangas@i 3607 [ # # ]: 0 : pq_putmessage_v2((edata->elevel < ERROR) ? 'N' : 'E', buf.data, buf.len + 1);
3608 : :
7661 tgl@sss.pgh.pa.us 3609 : 0 : pfree(buf.data);
3610 : : }
3611 : :
3612 : : /*
3613 : : * This flush is normally not necessary, since postgres.c will flush out
3614 : : * waiting data when control returns to the main loop. But it seems best
3615 : : * to leave it here, so that the client has some clue what happened if the
3616 : : * backend dies before getting back to the main loop ... error/notice
3617 : : * messages should not be a performance-critical path anyway, so an extra
3618 : : * flush won't hurt much ...
3619 : : */
8346 peter_e@gmx.net 3620 :CBC 97914 : pq_flush();
3621 : 97914 : }
3622 : :
3623 : :
3624 : : /*
3625 : : * Support routines for formatting error messages.
3626 : : */
3627 : :
3628 : :
3629 : : /*
3630 : : * error_severity --- get string representing elevel
3631 : : *
3632 : : * The string is not localized here, but we mark the strings for translation
3633 : : * so that callers can invoke _() on the result.
3634 : : */
3635 : : const char *
7661 tgl@sss.pgh.pa.us 3636 : 536077 : error_severity(int elevel)
3637 : : {
3638 : : const char *prefix;
3639 : :
3640 [ + + + + : 536077 : switch (elevel)
+ + + -
- ]
3641 : : {
8079 bruce@momjian.us 3642 : 2703 : case DEBUG1:
3643 : : case DEBUG2:
3644 : : case DEBUG3:
3645 : : case DEBUG4:
3646 : : case DEBUG5:
2788 tgl@sss.pgh.pa.us 3647 : 2703 : prefix = gettext_noop("DEBUG");
8346 peter_e@gmx.net 3648 : 2703 : break;
8079 bruce@momjian.us 3649 : 270109 : case LOG:
3650 : : case LOG_SERVER_ONLY:
2788 tgl@sss.pgh.pa.us 3651 : 270109 : prefix = gettext_noop("LOG");
8079 bruce@momjian.us 3652 : 270109 : break;
3653 : 283 : case INFO:
2788 tgl@sss.pgh.pa.us 3654 : 283 : prefix = gettext_noop("INFO");
8079 bruce@momjian.us 3655 : 283 : break;
8346 peter_e@gmx.net 3656 : 10922 : case NOTICE:
2788 tgl@sss.pgh.pa.us 3657 : 10922 : prefix = gettext_noop("NOTICE");
8346 peter_e@gmx.net 3658 : 10922 : break;
8075 bruce@momjian.us 3659 : 210794 : case WARNING:
3660 : : case WARNING_CLIENT_ONLY:
2788 tgl@sss.pgh.pa.us 3661 : 210794 : prefix = gettext_noop("WARNING");
8075 bruce@momjian.us 3662 : 210794 : break;
8346 peter_e@gmx.net 3663 : 40128 : case ERROR:
2788 tgl@sss.pgh.pa.us 3664 : 40128 : prefix = gettext_noop("ERROR");
8346 peter_e@gmx.net 3665 : 40128 : break;
3666 : 1138 : case FATAL:
2788 tgl@sss.pgh.pa.us 3667 : 1138 : prefix = gettext_noop("FATAL");
8346 peter_e@gmx.net 3668 : 1138 : break;
8079 bruce@momjian.us 3669 :UBC 0 : case PANIC:
2788 tgl@sss.pgh.pa.us 3670 : 0 : prefix = gettext_noop("PANIC");
7661 3671 : 0 : break;
3672 : 0 : default:
3673 : 0 : prefix = "???";
8346 peter_e@gmx.net 3674 : 0 : break;
3675 : : }
3676 : :
8346 peter_e@gmx.net 3677 :CBC 536077 : return prefix;
3678 : : }
3679 : :
3680 : :
3681 : : /*
3682 : : * append_with_tabs
3683 : : *
3684 : : * Append the string to the StringInfo buffer, inserting a tab after any
3685 : : * newline.
3686 : : */
3687 : : static void
7485 tgl@sss.pgh.pa.us 3688 : 646831 : append_with_tabs(StringInfo buf, const char *str)
3689 : : {
3690 : : char ch;
3691 : :
3692 [ + + ]: 120892342 : while ((ch = *str++) != '\0')
3693 : : {
3694 [ + + ]: 120245511 : appendStringInfoCharMacro(buf, ch);
3695 [ + + ]: 120245511 : if (ch == '\n')
3696 [ + + ]: 1109340 : appendStringInfoCharMacro(buf, '\t');
3697 : : }
7494 bruce@momjian.us 3698 : 646831 : }
3699 : :
3700 : :
3701 : : /*
3702 : : * Write errors to stderr (or by equal means when stderr is
3703 : : * not available). Used before ereport/elog can be used
3704 : : * safely (memory context, GUC load etc)
3705 : : */
3706 : : void
7234 tgl@sss.pgh.pa.us 3707 :UBC 0 : write_stderr(const char *fmt,...)
3708 : : {
3709 : : va_list ap;
3710 : :
3711 : : #ifdef WIN32
3712 : : char errbuf[2048]; /* Arbitrary size? */
3713 : : #endif
3714 : :
6991 bruce@momjian.us 3715 : 0 : fmt = _(fmt);
3716 : :
7234 tgl@sss.pgh.pa.us 3717 : 0 : va_start(ap, fmt);
3718 : : #ifndef WIN32
3719 : : /* On Unix, we just fprintf to stderr */
3720 : 0 : vfprintf(stderr, fmt, ap);
6149 andrew@dunslane.net 3721 : 0 : fflush(stderr);
3722 : : #else
3723 : : vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
3724 : :
3725 : : /*
3726 : : * On Win32, we print to stderr if running on a console, or write to
3727 : : * eventlog if running as a service
3728 : : */
3729 : : if (pgwin32_is_service()) /* Running as a service */
3730 : : {
3731 : : write_eventlog(ERROR, errbuf, strlen(errbuf));
3732 : : }
3733 : : else
3734 : : {
3735 : : /* Not running as service, write to stderr */
3736 : : write_console(errbuf, strlen(errbuf));
3737 : : fflush(stderr);
3738 : : }
3739 : : #endif
7234 tgl@sss.pgh.pa.us 3740 : 0 : va_end(ap);
3741 : 0 : }
|