#include "postgres.h"
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include "access/transam.h"
#include "access/xact.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "postmaster/syslogger.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "tcop/tcopprot.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
Go to the source code of this file.
Defines | |
#define | _(x) err_gettext(x) |
#define | ERRORDATA_STACK_SIZE 5 |
#define | FORMATTED_TS_LEN 128 |
#define | CHECK_STACK_DEPTH() |
#define | EVALUATE_MESSAGE(domain, targetfield, appendval, translateit) |
#define | EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval) |
Functions | |
static const char * | err_gettext (const char *str) __attribute__((format_arg(1))) |
static void | set_errdata_field (char **ptr, const char *str) |
static void | write_console (const char *line, int len) |
static void | log_line_prefix (StringInfo buf, ErrorData *edata) |
static void | send_message_to_server_log (ErrorData *edata) |
static void | send_message_to_frontend (ErrorData *edata) |
static char * | expand_fmt_string (const char *fmt, ErrorData *edata) |
static const char * | useful_strerror (int errnum) |
static const char * | error_severity (int elevel) |
static void | append_with_tabs (StringInfo buf, const char *str) |
static bool | is_log_level_output (int elevel, int log_min_level) |
static void | write_pipe_chunks (char *data, int len, int dest) |
static void | write_csvlog (ErrorData *edata) |
static void | setup_formatted_log_time (void) |
static void | setup_formatted_start_time (void) |
bool | in_error_recursion_trouble (void) |
bool | errstart (int elevel, const char *filename, int lineno, const char *funcname, const char *domain) |
void | errfinish (int dummy,...) |
int | errcode (int sqlerrcode) |
int | errcode_for_file_access (void) |
int | errcode_for_socket_access (void) |
int | errmsg (const char *fmt,...) |
int | errmsg_internal (const char *fmt,...) |
int | errmsg_plural (const char *fmt_singular, const char *fmt_plural, unsigned long n,...) |
int | errdetail (const char *fmt,...) |
int | errdetail_internal (const char *fmt,...) |
int | errdetail_log (const char *fmt,...) |
int | errdetail_plural (const char *fmt_singular, const char *fmt_plural, unsigned long n,...) |
int | errhint (const char *fmt,...) |
int | errcontext_msg (const char *fmt,...) |
int | set_errcontext_domain (const char *domain) |
int | errhidestmt (bool hide_stmt) |
int | errfunction (const char *funcname) |
int | errposition (int cursorpos) |
int | internalerrposition (int cursorpos) |
int | internalerrquery (const char *query) |
int | err_generic_string (int field, const char *str) |
int | geterrcode (void) |
int | geterrposition (void) |
int | getinternalerrposition (void) |
void | elog_start (const char *filename, int lineno, const char *funcname) |
void | elog_finish (int elevel, const char *fmt,...) |
void | pre_format_elog_string (int errnumber, const char *domain) |
char * | format_elog_string (const char *fmt,...) |
void | EmitErrorReport (void) |
ErrorData * | CopyErrorData (void) |
void | FreeErrorData (ErrorData *edata) |
void | FlushErrorState (void) |
void | ReThrowError (ErrorData *edata) |
void | pg_re_throw (void) |
void | DebugFileOpen (void) |
static void | appendCSVLiteral (StringInfo buf, const char *data) |
char * | unpack_sql_state (int sql_state) |
static void | err_sendstring (StringInfo buf, const char *str) |
void | write_stderr (const char *fmt,...) |
int | trace_recovery (int trace_level) |
Variables | |
ErrorContextCallback * | error_context_stack = NULL |
sigjmp_buf * | PG_exception_stack = NULL |
bool | redirection_done |
emit_log_hook_type | emit_log_hook = NULL |
int | Log_error_verbosity = PGERROR_VERBOSE |
char * | Log_line_prefix = NULL |
int | Log_destination = LOG_DESTINATION_STDERR |
static ErrorData | errordata [ERRORDATA_STACK_SIZE] |
static int | errordata_stack_depth = -1 |
static int | recursion_depth = 0 |
static char | formatted_start_time [FORMATTED_TS_LEN] |
static char | formatted_log_time [FORMATTED_TS_LEN] |
static int | save_format_errnumber |
static const char * | save_format_domain |
#define _ | ( | x | ) | err_gettext(x) |
Definition at line 83 of file elog.c.
Referenced by __attribute__(), _dosmaperr(), add_tablespace_footer(), addtt(), addtype(), adjust_data_dir(), advice(), associate(), ATWrongRelkindError(), BaseBackup(), bootstrap_template1(), check_authmethod_unspecified(), check_authmethod_valid(), check_input(), check_locale_encoding(), check_locale_name(), check_need_password(), check_ok(), CheckServerVersionForStreaming(), CleanupBackend(), CleanupBackgroundWorker(), ClientAuthentication(), close_walfile(), ClosePager(), cluster_all_databases(), cluster_one_database(), connectDatabase(), connection_warnings(), convert_sourcefiles_in(), convert_tuples_by_name(), convert_tuples_by_position(), ConvertTriggerToFK(), create_data_directory(), create_database(), create_role(), create_xlog_symlink(), dbState(), DeadLockReport(), describeAggregates(), describeFunctions(), DescribeLockTag(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describeRoles(), describeTablespaces(), describeTypes(), do_advice(), do_connect(), do_help(), do_init(), do_kill(), do_lo_list(), do_promote(), do_pset(), do_reload(), do_restart(), do_start(), do_status(), do_stop(), do_watch(), dolink(), drop_database_if_exists(), drop_role_if_exists(), DropErrorMsgWrongType(), dumpCreateDB(), dumpDatabases(), dumpTablespaces(), ecpg_start_test(), eitol(), error(), error_severity(), escape_quotes(), exec_command(), exec_execute_message(), executeCommand(), executeQuery(), existsTimeLineHistoryFile(), exit_nicely(), file_line_count(), file_size(), find_my_exec(), find_other_exec_or_die(), FindEndOfXLOG(), FindStreamingStart(), fsync_fname(), GenerateRecoveryConf(), get_encoding_id(), get_id(), get_object_address_unqualified(), get_opts(), get_pgpid(), get_restricted_token(), get_set_pwd(), get_user_name(), GetConnection(), getfields(), gethms(), getObjectDescription(), getOpFamilyDescription(), getRelationDescription(), handle_sigint(), handleCopyIn(), HandleCopyStream(), help(), helpSQL(), incompatible_module_error(), infile(), init_parallel_dump_utils(), initialize_data_directory(), initialize_environment(), inleap(), inlink(), inrule(), inzcont(), inzone(), inzsub(), isolation_start_test(), KillExistingArchiveStatus(), KillExistingXLOG(), leapadd(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listOneExtensionContents(), listSchemas(), listTables(), listTSConfigs(), listTSDictionaries(), listTSParsers(), listTSTemplates(), listUserMappings(), load_plpgsql(), load_resultmap(), log_child_failure(), log_line_prefix(), main(), MainLoop(), make_absolute_path(), make_directory(), make_postgres(), make_template0(), memcheck(), mkdatadir(), mkdirs(), newabbr(), oadd(), objectDescription(), open_result_files(), open_walfile(), outzone(), parse_psql_options(), pclose_check(), perform_fsync(), permissionsList(), pg_get_keywords(), pg_log(), pg_malloc(), pg_realloc(), pg_strdup(), pgfnames(), plpgsql_exec_error_callback(), plpgsql_stmt_typename(), popen_check(), pre_sync_fname(), print_aligned_vertical(), PrintControlValues(), printMixedStruct(), PrintNotifications(), printSSLInfo(), printTable(), printTableAddCell(), printTableAddHeader(), ProcSleep(), prompt_for_password(), psql_command(), psql_error(), psql_start_test(), PSQLexec(), reached_end_position(), read_post_opts(), ReadControlFile(), readfile(), reaper(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), ReceiveXlogStream(), regression_main(), reindex_all_databases(), reindex_one_database(), reindex_system_catalogs(), report_fork_failure_to_client(), report_invalid_record(), reportDependentObjects(), resolve_symlinks(), RewriteControlFile(), rewriteTargetView(), rmtree(), rpytime(), rulesub(), run_diff(), run_schedule(), run_single_test(), runPgDump(), send_message_to_frontend(), send_message_to_server_log(), sendFeedback(), SendQuery(), set_config_option(), set_dump_section(), set_mode(), set_null_conf(), set_sig(), setup_auth(), setup_bin_paths(), setup_collation(), setup_config(), setup_conversion(), setup_depend(), setup_description(), setup_dictionary(), setup_locale_encoding(), setup_pgdata(), setup_privileges(), setup_schema(), setup_sysviews(), setup_text_search(), show_cc(), show_cflags(), show_cflags_sl(), show_configure(), show_cppflags(), show_ldflags(), show_ldflags_ex(), show_ldflags_sl(), show_libs(), simple_prompt(), slashUsage(), spawn_process(), StartLogStreamer(), stop_postmaster(), stop_streaming(), storeObjectDescription(), StreamLog(), StreamServerPort(), strerror(), tadd(), test_config_settings(), test_postmaster_connection(), transformAggregateCall(), transformSubLink(), transformWindowFuncCall(), usage(), useful_strerror(), vacuum_all_databases(), vacuum_db(), vacuum_one_database(), verify_dir_is_empty_or_create(), vwrite_msg(), wait_for_tests(), wait_result_to_str(), wal_level_str(), walkdir(), warn_on_mount_point(), warning(), write_stderr(), write_version_file(), WriteEmptyXLOG(), writefile(), WriteRecoveryConf(), writeTarData(), writeTimeLineHistoryFile(), writezone(), yearistype(), and yesno_prompt().
#define CHECK_STACK_DEPTH | ( | ) |
do { \ if (errordata_stack_depth < 0) \ { \ errordata_stack_depth = -1; \ ereport(ERROR, (errmsg_internal("errstart was not called"))); \ } \ } while (0)
Definition at line 159 of file elog.c.
Referenced by CopyErrorData(), elog_finish(), EmitErrorReport(), err_generic_string(), errcode(), errcode_for_file_access(), errcode_for_socket_access(), errcontext_msg(), errdetail(), errdetail_internal(), errdetail_log(), errdetail_plural(), errfinish(), errfunction(), errhidestmt(), errhint(), errmsg(), errmsg_internal(), errmsg_plural(), errposition(), geterrcode(), geterrposition(), getinternalerrposition(), internalerrposition(), internalerrquery(), and set_errcontext_domain().
#define ERRORDATA_STACK_SIZE 5 |
Definition at line 141 of file elog.c.
Referenced by elog_start(), errstart(), and ReThrowError().
#define EVALUATE_MESSAGE | ( | domain, | ||
targetfield, | ||||
appendval, | ||||
translateit | ||||
) |
Definition at line 697 of file elog.c.
Referenced by elog_finish(), errcontext_msg(), errdetail(), errdetail_internal(), errdetail_log(), errhint(), errmsg(), errmsg_internal(), and format_elog_string().
#define EVALUATE_MESSAGE_PLURAL | ( | domain, | ||
targetfield, | ||||
appendval | ||||
) |
Definition at line 737 of file elog.c.
Referenced by errdetail_plural(), and errmsg_plural().
#define FORMATTED_TS_LEN 128 |
Definition at line 153 of file elog.c.
Referenced by setup_formatted_log_time(), and setup_formatted_start_time().
static void append_with_tabs | ( | StringInfo | buf, | |
const char * | str | |||
) | [static] |
Definition at line 3018 of file elog.c.
References appendStringInfoCharMacro.
Referenced by send_message_to_server_log().
{ char ch; while ((ch = *str++) != '\0') { appendStringInfoCharMacro(buf, ch); if (ch == '\n') appendStringInfoCharMacro(buf, '\t'); } }
static void appendCSVLiteral | ( | StringInfo | buf, | |
const char * | data | |||
) | [inline, static] |
Definition at line 2176 of file elog.c.
References appendStringInfoCharMacro, and NULL.
Referenced by write_csvlog().
{ const char *p = data; char c; /* avoid confusing an empty string with NULL */ if (p == NULL) return; appendStringInfoCharMacro(buf, '"'); while ((c = *p++) != '\0') { if (c == '"') appendStringInfoCharMacro(buf, '"'); appendStringInfoCharMacro(buf, c); } appendStringInfoCharMacro(buf, '"'); }
ErrorData* CopyErrorData | ( | void | ) |
Definition at line 1412 of file elog.c.
References Assert, CHECK_STACK_DEPTH, ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, CurrentMemoryContext, ErrorData::datatype_name, ErrorData::detail, ErrorData::detail_log, ErrorContext, ErrorData::hint, ErrorData::internalquery, ErrorData::message, palloc(), pstrdup(), ErrorData::schema_name, and ErrorData::table_name.
Referenced by exec_stmt_block(), initSuffixTree(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), pltcl_elog(), pltcl_subtrans_abort(), PLy_output(), PLy_spi_subtransaction_abort(), and xml_is_document().
{ ErrorData *edata = &errordata[errordata_stack_depth]; ErrorData *newedata; /* * we don't increment recursion_depth because out-of-memory here does not * indicate a problem within the error subsystem. */ CHECK_STACK_DEPTH(); Assert(CurrentMemoryContext != ErrorContext); /* Copy the struct itself */ newedata = (ErrorData *) palloc(sizeof(ErrorData)); memcpy(newedata, edata, sizeof(ErrorData)); /* Make copies of separately-allocated fields */ if (newedata->message) newedata->message = pstrdup(newedata->message); if (newedata->detail) newedata->detail = pstrdup(newedata->detail); if (newedata->detail_log) newedata->detail_log = pstrdup(newedata->detail_log); if (newedata->hint) newedata->hint = pstrdup(newedata->hint); if (newedata->context) newedata->context = pstrdup(newedata->context); if (newedata->schema_name) newedata->schema_name = pstrdup(newedata->schema_name); if (newedata->table_name) newedata->table_name = pstrdup(newedata->table_name); if (newedata->column_name) newedata->column_name = pstrdup(newedata->column_name); if (newedata->datatype_name) newedata->datatype_name = pstrdup(newedata->datatype_name); if (newedata->constraint_name) newedata->constraint_name = pstrdup(newedata->constraint_name); if (newedata->internalquery) newedata->internalquery = pstrdup(newedata->internalquery); return newedata; }
void DebugFileOpen | ( | void | ) |
Definition at line 1637 of file elog.c.
References close, ereport, errcode_for_file_access(), errmsg(), FATAL, IsUnderPostmaster, and OutputFileName.
Referenced by BaseInit().
{ int fd, istty; if (OutputFileName[0]) { /* * A debug-output file name was given. * * Make sure we can write the file, and find out if it's a tty. */ if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", OutputFileName))); istty = isatty(fd); close(fd); /* * Redirect our stderr to the debug output file. */ if (!freopen(OutputFileName, "a", stderr)) ereport(FATAL, (errcode_for_file_access(), errmsg("could not reopen file \"%s\" as stderr: %m", OutputFileName))); /* * If the file is a tty and we're running under the postmaster, try to * send stdout there as well (if it isn't a tty then stderr will block * out stdout, so we may as well let stdout go wherever it was going * before). */ if (istty && IsUnderPostmaster) if (!freopen(OutputFileName, "a", stdout)) ereport(FATAL, (errcode_for_file_access(), errmsg("could not reopen file \"%s\" as stdout: %m", OutputFileName))); } }
void elog_finish | ( | int | elevel, | |
const char * | fmt, | |||
... | ||||
) |
Definition at line 1270 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, errfinish(), ErrorContext, errstart(), EVALUATE_MESSAGE, ErrorData::filename, ErrorData::funcname, ErrorData::lineno, MemoryContextSwitchTo(), NULL, and ErrorData::saved_errno.
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; CHECK_STACK_DEPTH(); /* * Do errstart() to see if we actually want to report the message. */ errordata_stack_depth--; errno = edata->saved_errno; if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname, NULL)) return; /* nothing to do */ /* * Format error message just like errmsg_internal(). */ recursion_depth++; oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, message, false, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; /* * And let errfinish() finish up. */ errfinish(0); }
void elog_start | ( | const char * | filename, | |
int | lineno, | |||
const char * | funcname | |||
) |
Definition at line 1232 of file elog.c.
References ereport, errmsg_internal(), ERRORDATA_STACK_SIZE, ErrorData::filename, ErrorData::funcname, ErrorData::lineno, PANIC, and ErrorData::saved_errno.
{ ErrorData *edata; if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE) { /* * Wups, stack not big enough. We treat this as a PANIC condition * because it suggests an infinite loop of errors during error * recovery. Note that the message is intentionally not localized, * else failure to convert it to client encoding could cause further * recursion. */ errordata_stack_depth = -1; /* make room on stack */ ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded"))); } edata = &errordata[errordata_stack_depth]; if (filename) { const char *slash; /* keep only base name, useful especially for vpath builds */ slash = strrchr(filename, '/'); if (slash) filename = slash + 1; } edata->filename = filename; edata->lineno = lineno; edata->funcname = funcname; /* errno is saved now so that error parameter eval can't change it */ edata->saved_errno = errno; }
void EmitErrorReport | ( | void | ) |
Definition at line 1366 of file elog.c.
References CHECK_STACK_DEPTH, ErrorContext, MemoryContextSwitchTo(), ErrorData::output_to_client, ErrorData::output_to_server, send_message_to_frontend(), and send_message_to_server_log().
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWriterMain(), CheckpointerMain(), do_autovacuum(), do_start_bgworker(), errfinish(), PostgresMain(), and WalWriterMain().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); /* * Call hook before sending message to log. The hook function is allowed * to turn off edata->output_to_server, so we must recheck that afterward. * Making any other change in the content of edata is not considered * supported. * * Note: the reason why the hook can only turn off output_to_server, and * not turn it on, is that it'd be unreliable: we will never get here at * all if errstart() deems the message uninteresting. A hook that could * make decisions in that direction would have to hook into errstart(), * where it would have much less information available. emit_log_hook is * intended for custom log filtering and custom log message transmission * mechanisms. */ if (edata->output_to_server && emit_log_hook) (*emit_log_hook) (edata); /* Send to server log, if enabled */ if (edata->output_to_server) send_message_to_server_log(edata); /* Send to client, if enabled */ if (edata->output_to_client) send_message_to_frontend(edata); MemoryContextSwitchTo(oldcontext); recursion_depth--; }
int err_generic_string | ( | int | field, | |
const char * | str | |||
) |
Definition at line 1125 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::column_name, ErrorData::constraint_name, ErrorData::datatype_name, elog, ERROR, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_DATATYPE_NAME, PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, ErrorData::schema_name, set_errdata_field(), and ErrorData::table_name.
Referenced by errdatatype(), errdomainconstraint(), errtable(), errtablecolname(), and errtableconstraint().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); switch (field) { case PG_DIAG_SCHEMA_NAME: set_errdata_field(&edata->schema_name, str); break; case PG_DIAG_TABLE_NAME: set_errdata_field(&edata->table_name, str); break; case PG_DIAG_COLUMN_NAME: set_errdata_field(&edata->column_name, str); break; case PG_DIAG_DATATYPE_NAME: set_errdata_field(&edata->datatype_name, str); break; case PG_DIAG_CONSTRAINT_NAME: set_errdata_field(&edata->constraint_name, str); break; default: elog(ERROR, "unsupported ErrorData field id: %d", field); break; } return 0; /* return value does not matter */ }
static const char * err_gettext | ( | const char * | str | ) | [inline, static] |
Definition at line 203 of file elog.c.
References gettext, and in_error_recursion_trouble().
{ #ifdef ENABLE_NLS if (in_error_recursion_trouble()) return str; else return gettext(str); #else return str; #endif }
static void err_sendstring | ( | StringInfo | buf, | |
const char * | str | |||
) | [static] |
Definition at line 2686 of file elog.c.
References in_error_recursion_trouble(), pq_send_ascii_string(), and pq_sendstring().
Referenced by send_message_to_frontend().
{ if (in_error_recursion_trouble()) pq_send_ascii_string(buf, str); else pq_sendstring(buf, str); }
int errcode | ( | int | sqlerrcode | ) |
Definition at line 564 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::sqlerrcode.
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->sqlerrcode = sqlerrcode; return 0; /* return value does not matter */ }
int errcode_for_file_access | ( | void | ) |
Definition at line 587 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::saved_errno, and ErrorData::sqlerrcode.
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); switch (edata->saved_errno) { /* Permission-denied failures */ case EPERM: /* Not super-user */ case EACCES: /* Permission denied */ #ifdef EROFS case EROFS: /* Read only file system */ #endif edata->sqlerrcode = ERRCODE_INSUFFICIENT_PRIVILEGE; break; /* File not found */ case ENOENT: /* No such file or directory */ edata->sqlerrcode = ERRCODE_UNDEFINED_FILE; break; /* Duplicate file */ case EEXIST: /* File exists */ edata->sqlerrcode = ERRCODE_DUPLICATE_FILE; break; /* Wrong object type or state */ case ENOTDIR: /* Not a directory */ case EISDIR: /* Is a directory */ #if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */ case ENOTEMPTY: /* Directory not empty */ #endif edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE; break; /* Insufficient resources */ case ENOSPC: /* No space left on device */ edata->sqlerrcode = ERRCODE_DISK_FULL; break; case ENFILE: /* File table overflow */ case EMFILE: /* Too many open files */ edata->sqlerrcode = ERRCODE_INSUFFICIENT_RESOURCES; break; /* Hardware failure */ case EIO: /* I/O error */ edata->sqlerrcode = ERRCODE_IO_ERROR; break; /* All else is classified as internal errors */ default: edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; break; } return 0; /* return value does not matter */ }
int errcode_for_socket_access | ( | void | ) |
Definition at line 658 of file elog.c.
References CHECK_STACK_DEPTH, ECONNRESET, ErrorData::saved_errno, and ErrorData::sqlerrcode.
Referenced by ident_inet(), InitPostmasterDeathWatchHandle(), internal_flush(), libpq_select(), pgstat_init(), PgstatCollectorMain(), pq_getbyte_if_available(), pq_recvbuf(), ProcessStartupPacket(), ServerLoop(), StreamConnection(), StreamServerPort(), SysLogger_Start(), SysLoggerMain(), and WaitLatchOrSocket().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); switch (edata->saved_errno) { /* Loss of connection */ case EPIPE: #ifdef ECONNRESET case ECONNRESET: #endif edata->sqlerrcode = ERRCODE_CONNECTION_FAILURE; break; /* All else is classified as internal errors */ default: edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; break; } return 0; /* return value does not matter */ }
int errcontext_msg | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 976 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::context_domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->context_domain, context, true, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errdetail | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 859 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, detail, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errdetail_internal | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 886 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
Referenced by call_bool_check_hook(), call_enum_check_hook(), call_int_check_hook(), call_real_check_hook(), call_string_check_hook(), CheckForSerializableConflictIn(), CheckForSerializableConflictOut(), ClosePipeToProgram(), connect_pg_server(), ConvertTriggerToFK(), dblink_connect(), dblink_res_error(), DeadLockReport(), DropRole(), elog_node_display(), exec_stmt_raise(), incompatible_module_error(), OnConflict_CheckForSerializationFailure(), pgfdw_report_error(), PLy_elog(), PreCommit_CheckForSerializationFailure(), rewriteTargetView(), and ShowUsage().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, detail, false, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errdetail_log | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 907 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, detail_log, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errdetail_plural | ( | const char * | fmt_singular, | |
const char * | fmt_plural, | |||
unsigned long | n, | |||
... | ||||
) |
Definition at line 929 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE_PLURAL, and MemoryContextSwitchTo().
Referenced by errdetail_busy_db(), ExecEvalWholeRowVar(), and tupledesc_match().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE_PLURAL(edata->domain, detail, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
void errfinish | ( | int | dummy, | |
... | ||||
) |
Definition at line 393 of file elog.c.
References ErrorContextCallback::arg, ErrorContextCallback::callback, CHECK_FOR_INTERRUPTS, CHECK_STACK_DEPTH, ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, CritSectionCount, ErrorData::datatype_name, DestRemote, ErrorData::detail, ErrorData::detail_log, ErrorData::elevel, elevel, EmitErrorReport(), ERROR, ErrorContext, FATAL, ErrorData::hint, ImmediateInterruptOK, ErrorData::internalquery, InterruptHoldoffCount, MemoryContextSwitchTo(), ErrorData::message, NULL, PANIC, pfree(), PG_RE_THROW, pq_endcopyout(), ErrorContextCallback::previous, proc_exit(), ErrorData::schema_name, ErrorData::table_name, and whereToSendOutput.
{ ErrorData *edata = &errordata[errordata_stack_depth]; int elevel = edata->elevel; MemoryContext oldcontext; ErrorContextCallback *econtext; recursion_depth++; CHECK_STACK_DEPTH(); /* * Do processing in ErrorContext, which we hope has enough reserved space * to report an error. */ oldcontext = MemoryContextSwitchTo(ErrorContext); /* * Call any context callback functions. Errors occurring in callback * functions will be treated as recursive errors --- this ensures we will * avoid infinite recursion (see errstart). */ for (econtext = error_context_stack; econtext != NULL; econtext = econtext->previous) (*econtext->callback) (econtext->arg); /* * If ERROR (not more nor less) we pass it off to the current handler. * Printing it and popping the stack is the responsibility of the handler. */ if (elevel == ERROR) { /* * We do some minimal cleanup before longjmp'ing so that handlers can * execute in a reasonably sane state. */ /* This is just in case the error came while waiting for input */ ImmediateInterruptOK = false; /* * Reset InterruptHoldoffCount in case we ereport'd from inside an * interrupt holdoff section. (We assume here that no handler will * itself be inside a holdoff section. If necessary, such a handler * could save and restore InterruptHoldoffCount for itself, but this * should make life easier for most.) */ InterruptHoldoffCount = 0; CritSectionCount = 0; /* should be unnecessary, but... */ /* * Note that we leave CurrentMemoryContext set to ErrorContext. The * handler should reset it to something else soon. */ recursion_depth--; PG_RE_THROW(); } /* * If we are doing FATAL or PANIC, abort any old-style COPY OUT in * progress, so that we can report the message before dying. (Without * this, pq_putmessage will refuse to send the message at all, which is * what we want for NOTICE messages, but not for fatal exits.) This hack * is necessary because of poor design of old-style copy protocol. Note * we must do this even if client is fool enough to have set * client_min_messages above FATAL, so don't look at output_to_client. */ if (elevel >= FATAL && whereToSendOutput == DestRemote) pq_endcopyout(true); /* Emit the message to the right places */ EmitErrorReport(); /* Now free up subsidiary data attached to stack entry, and release it */ if (edata->message) pfree(edata->message); if (edata->detail) pfree(edata->detail); if (edata->detail_log) pfree(edata->detail_log); if (edata->hint) pfree(edata->hint); if (edata->context) pfree(edata->context); if (edata->schema_name) pfree(edata->schema_name); if (edata->table_name) pfree(edata->table_name); if (edata->column_name) pfree(edata->column_name); if (edata->datatype_name) pfree(edata->datatype_name); if (edata->constraint_name) pfree(edata->constraint_name); if (edata->internalquery) pfree(edata->internalquery); errordata_stack_depth--; /* Exit error-handling context */ MemoryContextSwitchTo(oldcontext); recursion_depth--; /* * Perform error recovery action as specified by elevel. */ if (elevel == FATAL) { /* * For a FATAL error, we let proc_exit clean up and exit. */ ImmediateInterruptOK = false; /* * If we just reported a startup failure, the client will disconnect * on receiving it, so don't send any more to the client. */ if (PG_exception_stack == NULL && whereToSendOutput == DestRemote) whereToSendOutput = DestNone; /* * fflush here is just to improve the odds that we get to see the * error message, in case things are so hosed that proc_exit crashes. * Any other code you might be tempted to add here should probably be * in an on_proc_exit or on_shmem_exit callback instead. */ fflush(stdout); fflush(stderr); /* * Do normal process-exit cleanup, then return exit code 1 to indicate * FATAL termination. The postmaster may or may not consider this * worthy of panic, depending on which subprocess returns it. */ proc_exit(1); } if (elevel >= PANIC) { /* * Serious crash time. Postmaster will observe SIGABRT process exit * status and kill the other backends too. * * XXX: what if we are *in* the postmaster? abort() won't kill our * children... */ ImmediateInterruptOK = false; fflush(stdout); fflush(stderr); abort(); } /* * We reach here if elevel <= WARNING. OK to return to caller. * * But check for cancel/die interrupt first --- this is so that the user * can stop a query emitting tons of notice or warning messages, even if * it's in a loop that otherwise fails to check for interrupts. */ CHECK_FOR_INTERRUPTS(); }
int errfunction | ( | const char * | funcname | ) |
Definition at line 1042 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::funcname, and ErrorData::show_funcname.
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->funcname = funcname; edata->show_funcname = true; return 0; /* return value does not matter */ }
int errhidestmt | ( | bool | hide_stmt | ) |
Definition at line 1021 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::hide_stmt.
Referenced by exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), and explain_ExecutorEnd().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->hide_stmt = hide_stmt; return 0; /* return value does not matter */ }
int errhint | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 951 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, hint, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errmsg | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 786 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, message, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errmsg_internal | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 815 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, and MemoryContextSwitchTo().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, message, false, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
int errmsg_plural | ( | const char * | fmt_singular, | |
const char * | fmt_plural, | |||
unsigned long | n, | |||
... | ||||
) |
Definition at line 837 of file elog.c.
References CHECK_STACK_DEPTH, ErrorData::domain, ErrorContext, EVALUATE_MESSAGE_PLURAL, and MemoryContextSwitchTo().
Referenced by CheckpointerMain(), exec_eval_expr(), func_select_candidate(), init_fcache(), LookupAggNameTypeNames(), LookupFuncNameTypeNames(), ParseFuncOrColumn(), ProcedureCreate(), and reportDependentObjects().
{ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE_PLURAL(edata->domain, message, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */ }
static const char * error_severity | ( | int | elevel | ) | [static] |
Definition at line 2967 of file elog.c.
References _, COMMERROR, DEBUG1, DEBUG2, DEBUG3, DEBUG4, DEBUG5, ERROR, FATAL, INFO, LOG, NOTICE, PANIC, and WARNING.
Referenced by send_message_to_frontend(), send_message_to_server_log(), and write_csvlog().
{ const char *prefix; switch (elevel) { case DEBUG1: case DEBUG2: case DEBUG3: case DEBUG4: case DEBUG5: prefix = _("DEBUG"); break; case LOG: case COMMERROR: prefix = _("LOG"); break; case INFO: prefix = _("INFO"); break; case NOTICE: prefix = _("NOTICE"); break; case WARNING: prefix = _("WARNING"); break; case ERROR: prefix = _("ERROR"); break; case FATAL: prefix = _("FATAL"); break; case PANIC: prefix = _("PANIC"); break; default: prefix = "???"; break; } return prefix; }
int errposition | ( | int | cursorpos | ) |
Definition at line 1059 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::cursorpos.
Referenced by _SPI_error_callback(), function_parse_error_transpose(), parser_errposition(), pts_error_callback(), sql_exec_error_callback(), and sql_inline_error_callback().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->cursorpos = cursorpos; return 0; /* return value does not matter */ }
bool errstart | ( | int | elevel, | |
const char * | filename, | |||
int | lineno, | |||
const char * | funcname, | |||
const char * | domain | |||
) |
Definition at line 228 of file elog.c.
References client_min_messages, ClientAuthInProgress, COMMERROR, CritSectionCount, debug_query_string, DestRemote, ErrorData::domain, ErrorData::elevel, ereport, errmsg_internal(), ERROR, ErrorContext, ERRORDATA_STACK_SIZE, ExitOnAnyError, ErrorData::filename, ErrorData::funcname, i, in_error_recursion_trouble(), is_log_level_output(), IsPostmasterEnvironment, ErrorData::lineno, log_min_messages, Max, MemoryContextReset(), MemSet, NULL, ErrorData::output_to_client, ErrorData::output_to_server, PANIC, PG_TEXTDOMAIN, proc_exit_inprogress, ErrorData::saved_errno, ErrorData::sqlerrcode, WARNING, and whereToSendOutput.
{ ErrorData *edata; bool output_to_server; bool output_to_client = false; int i; /* * Check some cases in which we want to promote an error into a more * severe error. None of this logic applies for non-error messages. */ if (elevel >= ERROR) { /* * If we are inside a critical section, all errors become PANIC * errors. See miscadmin.h. */ if (CritSectionCount > 0) elevel = PANIC; /* * Check reasons for treating ERROR as FATAL: * * 1. we have no handler to pass the error to (implies we are in the * postmaster or in backend startup). * * 2. ExitOnAnyError mode switch is set (initdb uses this). * * 3. the error occurred after proc_exit has begun to run. (It's * proc_exit's responsibility to see that this doesn't turn into * infinite recursion!) */ if (elevel == ERROR) { if (PG_exception_stack == NULL || ExitOnAnyError || proc_exit_inprogress) elevel = FATAL; } /* * If the error level is ERROR or more, errfinish is not going to * return to caller; therefore, if there is any stacked error already * in progress it will be lost. This is more or less okay, except we * do not want to have a FATAL or PANIC error downgraded because the * reporting process was interrupted by a lower-grade error. So check * the stack and make sure we panic if panic is warranted. */ for (i = 0; i <= errordata_stack_depth; i++) elevel = Max(elevel, errordata[i].elevel); } /* * Now decide whether we need to process this report at all; if it's * warning or less and not enabled for logging, just return FALSE without * starting up any error logging machinery. */ /* Determine whether message is enabled for server log output */ if (IsPostmasterEnvironment) output_to_server = is_log_level_output(elevel, log_min_messages); else /* In bootstrap/standalone case, do not sort LOG out-of-order */ output_to_server = (elevel >= log_min_messages); /* Determine whether message is enabled for client output */ if (whereToSendOutput == DestRemote && elevel != COMMERROR) { /* * client_min_messages is honored only after we complete the * authentication handshake. This is required both for security * reasons and because many clients can't handle NOTICE messages * during authentication. */ if (ClientAuthInProgress) output_to_client = (elevel >= ERROR); else output_to_client = (elevel >= client_min_messages || elevel == INFO); } /* Skip processing effort if non-error message will not be output */ if (elevel < ERROR && !output_to_server && !output_to_client) return false; /* * Okay, crank up a stack entry to store the info in. */ if (recursion_depth++ > 0 && elevel >= ERROR) { /* * Ooops, error during error processing. Clear ErrorContext as * discussed at top of file. We will not return to the original * error's reporter or handler, so we don't need it. */ MemoryContextReset(ErrorContext); /* * Infinite error recursion might be due to something broken in a * context traceback routine. Abandon them too. We also abandon * attempting to print the error statement (which, if long, could * itself be the source of the recursive failure). */ if (in_error_recursion_trouble()) { error_context_stack = NULL; debug_query_string = NULL; } } if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE) { /* * Wups, stack not big enough. We treat this as a PANIC condition * because it suggests an infinite loop of errors during error * recovery. */ errordata_stack_depth = -1; /* make room on stack */ ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded"))); } /* Initialize data for this error frame */ edata = &errordata[errordata_stack_depth]; MemSet(edata, 0, sizeof(ErrorData)); edata->elevel = elevel; edata->output_to_server = output_to_server; edata->output_to_client = output_to_client; if (filename) { const char *slash; /* keep only base name, useful especially for vpath builds */ slash = strrchr(filename, '/'); if (slash) filename = slash + 1; } edata->filename = filename; edata->lineno = lineno; edata->funcname = funcname; /* the default text domain is the backend's */ edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres"); /* Select default errcode based on elevel */ if (elevel >= ERROR) edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; else if (elevel == WARNING) edata->sqlerrcode = ERRCODE_WARNING; else edata->sqlerrcode = ERRCODE_SUCCESSFUL_COMPLETION; /* errno is saved here so that error parameter eval can't change it */ edata->saved_errno = errno; recursion_depth--; return true; }
static char * expand_fmt_string | ( | const char * | fmt, | |
ErrorData * | edata | |||
) | [static] |
Definition at line 2884 of file elog.c.
References appendStringInfoCharMacro, StringInfoData::data, initStringInfo(), ErrorData::saved_errno, and useful_strerror().
{ StringInfoData buf; const char *cp; initStringInfo(&buf); for (cp = fmt; *cp; cp++) { if (cp[0] == '%' && cp[1] != '\0') { cp++; if (*cp == 'm') { /* * Replace %m by system error string. If there are any %'s in * the string, we'd better double them so that vsnprintf won't * misinterpret. */ const char *cp2; cp2 = useful_strerror(edata->saved_errno); for (; *cp2; cp2++) { if (*cp2 == '%') appendStringInfoCharMacro(&buf, '%'); appendStringInfoCharMacro(&buf, *cp2); } } else { /* copy % and next char --- this avoids trouble with %%m */ appendStringInfoCharMacro(&buf, '%'); appendStringInfoCharMacro(&buf, *cp); } } else appendStringInfoCharMacro(&buf, *cp); } return buf.data; }
void FlushErrorState | ( | void | ) |
Definition at line 1499 of file elog.c.
References ErrorContext, and MemoryContextResetAndDeleteChildren().
Referenced by AutoVacLauncherMain(), BackgroundWriterMain(), call_bool_check_hook(), call_enum_check_hook(), call_int_check_hook(), call_real_check_hook(), call_string_check_hook(), CheckpointerMain(), do_autovacuum(), exec_stmt_block(), initSuffixTree(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), pltcl_elog(), pltcl_subtrans_abort(), PLy_output(), PLy_spi_subtransaction_abort(), PostgresMain(), WalWriterMain(), and xml_is_document().
{ /* * Reset stack to empty. The only case where it would be more than one * deep is if we serviced an error that interrupted construction of * another message. We assume control escaped out of that message * construction and won't ever go back. */ errordata_stack_depth = -1; recursion_depth = 0; /* Delete all data in ErrorContext */ MemoryContextResetAndDeleteChildren(ErrorContext); }
char* format_elog_string | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 1334 of file elog.c.
References ErrorData::domain, ErrorContext, EVALUATE_MESSAGE, MemoryContextSwitchTo(), MemSet, ErrorData::message, PG_TEXTDOMAIN, and ErrorData::saved_errno.
{ ErrorData errdata; ErrorData *edata; MemoryContext oldcontext; /* Initialize a mostly-dummy error frame */ edata = &errdata; MemSet(edata, 0, sizeof(ErrorData)); /* the default text domain is the backend's */ edata->domain = save_format_domain ? save_format_domain : PG_TEXTDOMAIN("postgres"); /* set the errno to be used to interpret %m */ edata->saved_errno = save_format_errnumber; oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(edata->domain, message, false, true); MemoryContextSwitchTo(oldcontext); return edata->message; }
void FreeErrorData | ( | ErrorData * | edata | ) |
Definition at line 1463 of file elog.c.
References ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, ErrorData::datatype_name, ErrorData::detail, ErrorData::detail_log, ErrorData::hint, ErrorData::internalquery, ErrorData::message, pfree(), ErrorData::schema_name, and ErrorData::table_name.
Referenced by exec_stmt_block(), pltcl_elog(), pltcl_subtrans_abort(), and PLy_spi_subtransaction_abort().
{ if (edata->message) pfree(edata->message); if (edata->detail) pfree(edata->detail); if (edata->detail_log) pfree(edata->detail_log); if (edata->hint) pfree(edata->hint); if (edata->context) pfree(edata->context); if (edata->schema_name) pfree(edata->schema_name); if (edata->table_name) pfree(edata->table_name); if (edata->column_name) pfree(edata->column_name); if (edata->datatype_name) pfree(edata->datatype_name); if (edata->constraint_name) pfree(edata->constraint_name); if (edata->internalquery) pfree(edata->internalquery); pfree(edata); }
int geterrcode | ( | void | ) |
Definition at line 1174 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::sqlerrcode.
Referenced by pcb_error_callback().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); return edata->sqlerrcode; }
int geterrposition | ( | void | ) |
Definition at line 1191 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::cursorpos.
Referenced by _SPI_error_callback(), function_parse_error_transpose(), sql_exec_error_callback(), and sql_inline_error_callback().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); return edata->cursorpos; }
int getinternalerrposition | ( | void | ) |
Definition at line 1208 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::internalpos.
Referenced by function_parse_error_transpose().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); return edata->internalpos; }
bool in_error_recursion_trouble | ( | void | ) |
Definition at line 191 of file elog.c.
Referenced by err_gettext(), err_sendstring(), errstart(), and write_console().
{ /* Pull the plug if recurse more than once */ return (recursion_depth > 2); }
int internalerrposition | ( | int | cursorpos | ) |
Definition at line 1075 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::internalpos.
Referenced by _SPI_error_callback(), function_parse_error_transpose(), plpgsql_scanner_errposition(), PLy_elog(), sql_exec_error_callback(), and sql_inline_error_callback().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->internalpos = cursorpos; return 0; /* return value does not matter */ }
int internalerrquery | ( | const char * | query | ) |
Definition at line 1095 of file elog.c.
References CHECK_STACK_DEPTH, ErrorContext, ErrorData::internalquery, MemoryContextStrdup(), and pfree().
Referenced by _SPI_error_callback(), function_parse_error_transpose(), plpgsql_scanner_errposition(), PLy_elog(), sql_exec_error_callback(), and sql_inline_error_callback().
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); if (edata->internalquery) { pfree(edata->internalquery); edata->internalquery = NULL; } if (query) edata->internalquery = MemoryContextStrdup(ErrorContext, query); return 0; /* return value does not matter */ }
static bool is_log_level_output | ( | int | elevel, | |
int | log_min_level | |||
) | [static] |
Definition at line 3083 of file elog.c.
References COMMERROR, ERROR, FATAL, and LOG.
Referenced by errstart(), pg_re_throw(), send_message_to_server_log(), and write_csvlog().
static void log_line_prefix | ( | StringInfo | buf, | |
ErrorData * | edata | |||
) | [static] |
Definition at line 2013 of file elog.c.
References _, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), application_name, PGPROC::backendId, Port::database_name, get_ps_display(), GetTopTransactionIdIfAny(), InvalidBackendId, log_timezone, PGPROC::lxid, MyProc, MyProcPid, MyProcPort, MyStartTime, NULL, pg_localtime(), pg_strftime(), Port::remote_host, Port::remote_port, setup_formatted_log_time(), setup_formatted_start_time(), ErrorData::sqlerrcode, unpack_sql_state(), Port::user_name, and username.
Referenced by send_message_to_server_log().
{ /* static counter for line numbers */ static long log_line_number = 0; /* has counter been reset in current process? */ static int log_my_pid = 0; int format_len; int i; /* * This is one of the few places where we'd rather not inherit a static * variable's value from the postmaster. But since we will, reset it when * MyProcPid changes. MyStartTime also changes when MyProcPid does, so * reset the formatted start timestamp too. */ if (log_my_pid != MyProcPid) { log_line_number = 0; log_my_pid = MyProcPid; formatted_start_time[0] = '\0'; } log_line_number++; if (Log_line_prefix == NULL) return; /* in case guc hasn't run yet */ format_len = strlen(Log_line_prefix); for (i = 0; i < format_len; i++) { if (Log_line_prefix[i] != '%') { /* literal char, just copy */ appendStringInfoChar(buf, Log_line_prefix[i]); continue; } /* go to char after '%' */ i++; if (i >= format_len) break; /* format error - ignore it */ /* process the option */ switch (Log_line_prefix[i]) { case 'a': if (MyProcPort) { const char *appname = application_name; if (appname == NULL || *appname == '\0') appname = _("[unknown]"); appendStringInfoString(buf, appname); } break; case 'u': if (MyProcPort) { const char *username = MyProcPort->user_name; if (username == NULL || *username == '\0') username = _("[unknown]"); appendStringInfoString(buf, username); } break; case 'd': if (MyProcPort) { const char *dbname = MyProcPort->database_name; if (dbname == NULL || *dbname == '\0') dbname = _("[unknown]"); appendStringInfoString(buf, dbname); } break; case 'c': appendStringInfo(buf, "%lx.%04x", (long) (MyStartTime), MyProcPid); break; case 'p': appendStringInfo(buf, "%d", MyProcPid); break; case 'l': appendStringInfo(buf, "%ld", log_line_number); break; case 'm': setup_formatted_log_time(); appendStringInfoString(buf, formatted_log_time); break; case 't': { pg_time_t stamp_time = (pg_time_t) time(NULL); char strfbuf[128]; pg_strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&stamp_time, log_timezone)); appendStringInfoString(buf, strfbuf); } break; case 's': if (formatted_start_time[0] == '\0') setup_formatted_start_time(); appendStringInfoString(buf, formatted_start_time); break; case 'i': if (MyProcPort) { const char *psdisp; int displen; psdisp = get_ps_display(&displen); appendBinaryStringInfo(buf, psdisp, displen); } break; case 'r': if (MyProcPort && MyProcPort->remote_host) { appendStringInfoString(buf, MyProcPort->remote_host); if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') appendStringInfo(buf, "(%s)", MyProcPort->remote_port); } break; case 'h': if (MyProcPort && MyProcPort->remote_host) appendStringInfoString(buf, MyProcPort->remote_host); break; case 'q': /* in postmaster and friends, stop if %q is seen */ /* in a backend, just ignore */ if (MyProcPort == NULL) i = format_len; break; case 'v': /* keep VXID format in sync with lockfuncs.c */ if (MyProc != NULL && MyProc->backendId != InvalidBackendId) appendStringInfo(buf, "%d/%u", MyProc->backendId, MyProc->lxid); break; case 'x': appendStringInfo(buf, "%u", GetTopTransactionIdIfAny()); break; case 'e': appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode)); break; case '%': appendStringInfoChar(buf, '%'); break; default: /* format error - ignore it */ break; } } }
void pg_re_throw | ( | void | ) |
Definition at line 1578 of file elog.c.
References Assert, client_min_messages, ClientAuthInProgress, DestRemote, ErrorData::elevel, errfinish(), ERROR, ExceptionalCondition(), FATAL, is_log_level_output(), IsPostmasterEnvironment, log_min_messages, NULL, ErrorData::output_to_client, ErrorData::output_to_server, siglongjmp, and whereToSendOutput.
{ /* If possible, throw the error to the next outer setjmp handler */ if (PG_exception_stack != NULL) siglongjmp(*PG_exception_stack, 1); else { /* * If we get here, elog(ERROR) was thrown inside a PG_TRY block, which * we have now exited only to discover that there is no outer setjmp * handler to pass the error to. Had the error been thrown outside * the block to begin with, we'd have promoted the error to FATAL, so * the correct behavior is to make it FATAL now; that is, emit it and * then call proc_exit. */ ErrorData *edata = &errordata[errordata_stack_depth]; Assert(errordata_stack_depth >= 0); Assert(edata->elevel == ERROR); edata->elevel = FATAL; /* * At least in principle, the increase in severity could have changed * where-to-output decisions, so recalculate. This should stay in * sync with errstart(), which see for comments. */ if (IsPostmasterEnvironment) edata->output_to_server = is_log_level_output(FATAL, log_min_messages); else edata->output_to_server = (FATAL >= log_min_messages); if (whereToSendOutput == DestRemote) { if (ClientAuthInProgress) edata->output_to_client = true; else edata->output_to_client = (FATAL >= client_min_messages); } /* * We can use errfinish() for the rest, but we don't want it to call * any error context routines a second time. Since we know we are * about to exit, it should be OK to just clear the context stack. */ error_context_stack = NULL; errfinish(0); } /* Doesn't return ... */ ExceptionalCondition("pg_re_throw tried to return", "FailedAssertion", __FILE__, __LINE__); }
void pre_format_elog_string | ( | int | errnumber, | |
const char * | domain | |||
) |
Definition at line 1325 of file elog.c.
{ /* Save errno before evaluation of argument functions can change it */ save_format_errnumber = errnumber; /* Save caller's text domain */ save_format_domain = domain; }
void ReThrowError | ( | ErrorData * | edata | ) |
Definition at line 1522 of file elog.c.
References Assert, ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, ErrorData::datatype_name, ErrorData::detail, ErrorData::detail_log, ErrorData::elevel, ereport, errmsg_internal(), ERROR, ErrorContext, ERRORDATA_STACK_SIZE, ErrorData::hint, ErrorData::internalquery, MemoryContextSwitchTo(), ErrorData::message, PANIC, PG_RE_THROW, pstrdup(), ErrorData::schema_name, and ErrorData::table_name.
Referenced by exec_stmt_block(), and exec_stmt_raise().
{ ErrorData *newedata; Assert(edata->elevel == ERROR); /* Push the data back into the error context */ recursion_depth++; MemoryContextSwitchTo(ErrorContext); if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE) { /* * Wups, stack not big enough. We treat this as a PANIC condition * because it suggests an infinite loop of errors during error * recovery. */ errordata_stack_depth = -1; /* make room on stack */ ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded"))); } newedata = &errordata[errordata_stack_depth]; memcpy(newedata, edata, sizeof(ErrorData)); /* Make copies of separately-allocated fields */ if (newedata->message) newedata->message = pstrdup(newedata->message); if (newedata->detail) newedata->detail = pstrdup(newedata->detail); if (newedata->detail_log) newedata->detail_log = pstrdup(newedata->detail_log); if (newedata->hint) newedata->hint = pstrdup(newedata->hint); if (newedata->context) newedata->context = pstrdup(newedata->context); if (newedata->schema_name) newedata->schema_name = pstrdup(newedata->schema_name); if (newedata->table_name) newedata->table_name = pstrdup(newedata->table_name); if (newedata->column_name) newedata->column_name = pstrdup(newedata->column_name); if (newedata->datatype_name) newedata->datatype_name = pstrdup(newedata->datatype_name); if (newedata->constraint_name) newedata->constraint_name = pstrdup(newedata->constraint_name); if (newedata->internalquery) newedata->internalquery = pstrdup(newedata->internalquery); recursion_depth--; PG_RE_THROW(); }
static void send_message_to_frontend | ( | ErrorData * | edata | ) | [static] |
Definition at line 2698 of file elog.c.
References _, appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), ErrorData::column_name, ErrorData::constraint_name, ErrorData::context, ErrorData::cursorpos, StringInfoData::data, ErrorData::datatype_name, ErrorData::detail, ErrorData::elevel, err_sendstring(), ERROR, error_severity(), ErrorData::filename, FrontendProtocol, ErrorData::funcname, ErrorData::hint, initStringInfo(), ErrorData::internalpos, ErrorData::internalquery, ErrorData::lineno, ErrorData::message, pfree(), PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_CONTEXT, PG_DIAG_DATATYPE_NAME, PG_DIAG_INTERNAL_POSITION, PG_DIAG_INTERNAL_QUERY, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SCHEMA_NAME, PG_DIAG_SEVERITY, PG_DIAG_SOURCE_FILE, PG_DIAG_SOURCE_FUNCTION, PG_DIAG_SOURCE_LINE, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PG_DIAG_TABLE_NAME, PG_PROTOCOL_MAJOR, PGUNSIXBIT, pq_beginmessage(), pq_endmessage(), pq_flush(), pq_sendbyte(), ErrorData::schema_name, ErrorData::show_funcname, snprintf(), ErrorData::sqlerrcode, and ErrorData::table_name.
Referenced by EmitErrorReport().
{ StringInfoData msgbuf; /* 'N' (Notice) is for nonfatal conditions, 'E' is for errors */ pq_beginmessage(&msgbuf, (edata->elevel < ERROR) ? 'N' : 'E'); if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { /* New style with separate fields */ char tbuf[12]; int ssval; int i; pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY); err_sendstring(&msgbuf, error_severity(edata->elevel)); /* unpack MAKE_SQLSTATE code */ ssval = edata->sqlerrcode; for (i = 0; i < 5; i++) { tbuf[i] = PGUNSIXBIT(ssval); ssval >>= 6; } tbuf[i] = '\0'; pq_sendbyte(&msgbuf, PG_DIAG_SQLSTATE); err_sendstring(&msgbuf, tbuf); /* M field is required per protocol, so always send something */ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY); if (edata->message) err_sendstring(&msgbuf, edata->message); else err_sendstring(&msgbuf, _("missing error text")); if (edata->detail) { pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL); err_sendstring(&msgbuf, edata->detail); } /* detail_log is intentionally not used here */ if (edata->hint) { pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT); err_sendstring(&msgbuf, edata->hint); } if (edata->context) { pq_sendbyte(&msgbuf, PG_DIAG_CONTEXT); err_sendstring(&msgbuf, edata->context); } if (edata->schema_name) { pq_sendbyte(&msgbuf, PG_DIAG_SCHEMA_NAME); err_sendstring(&msgbuf, edata->schema_name); } if (edata->table_name) { pq_sendbyte(&msgbuf, PG_DIAG_TABLE_NAME); err_sendstring(&msgbuf, edata->table_name); } if (edata->column_name) { pq_sendbyte(&msgbuf, PG_DIAG_COLUMN_NAME); err_sendstring(&msgbuf, edata->column_name); } if (edata->datatype_name) { pq_sendbyte(&msgbuf, PG_DIAG_DATATYPE_NAME); err_sendstring(&msgbuf, edata->datatype_name); } if (edata->constraint_name) { pq_sendbyte(&msgbuf, PG_DIAG_CONSTRAINT_NAME); err_sendstring(&msgbuf, edata->constraint_name); } if (edata->cursorpos > 0) { snprintf(tbuf, sizeof(tbuf), "%d", edata->cursorpos); pq_sendbyte(&msgbuf, PG_DIAG_STATEMENT_POSITION); err_sendstring(&msgbuf, tbuf); } if (edata->internalpos > 0) { snprintf(tbuf, sizeof(tbuf), "%d", edata->internalpos); pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_POSITION); err_sendstring(&msgbuf, tbuf); } if (edata->internalquery) { pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_QUERY); err_sendstring(&msgbuf, edata->internalquery); } if (edata->filename) { pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FILE); err_sendstring(&msgbuf, edata->filename); } if (edata->lineno > 0) { snprintf(tbuf, sizeof(tbuf), "%d", edata->lineno); pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_LINE); err_sendstring(&msgbuf, tbuf); } if (edata->funcname) { pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FUNCTION); err_sendstring(&msgbuf, edata->funcname); } pq_sendbyte(&msgbuf, '\0'); /* terminator */ } else { /* Old style --- gin up a backwards-compatible message */ StringInfoData buf; initStringInfo(&buf); appendStringInfo(&buf, "%s: ", error_severity(edata->elevel)); if (edata->show_funcname && edata->funcname) appendStringInfo(&buf, "%s: ", edata->funcname); if (edata->message) appendStringInfoString(&buf, edata->message); else appendStringInfoString(&buf, _("missing error text")); if (edata->cursorpos > 0) appendStringInfo(&buf, _(" at character %d"), edata->cursorpos); else if (edata->internalpos > 0) appendStringInfo(&buf, _(" at character %d"), edata->internalpos); appendStringInfoChar(&buf, '\n'); err_sendstring(&msgbuf, buf.data); pfree(buf.data); } pq_endmessage(&msgbuf); /* * This flush is normally not necessary, since postgres.c will flush out * waiting data when control returns to the main loop. But it seems best * to leave it here, so that the client has some clue what happened if the * backend dies before getting back to the main loop ... error/notice * messages should not be a performance-critical path anyway, so an extra * flush won't hurt much ... */ pq_flush(); }
static void send_message_to_server_log | ( | ErrorData * | edata | ) | [static] |
Definition at line 2416 of file elog.c.
References _, am_syslogger, append_with_tabs(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), COMMERROR, ErrorData::context, ErrorData::cursorpos, StringInfoData::data, DEBUG1, DEBUG2, DEBUG3, DEBUG4, DEBUG5, debug_query_string, DestDebug, ErrorData::detail, ErrorData::detail_log, ErrorData::elevel, ERROR, error_severity(), FATAL, ErrorData::filename, ErrorData::funcname, ErrorData::hide_stmt, ErrorData::hint, INFO, initStringInfo(), ErrorData::internalpos, ErrorData::internalquery, is_log_level_output(), StringInfoData::len, ErrorData::lineno, LOG, LOG_DESTINATION_CSVLOG, LOG_DESTINATION_EVENTLOG, LOG_DESTINATION_STDERR, LOG_DESTINATION_SYSLOG, log_line_prefix(), log_min_error_statement, ErrorData::message, NOTICE, NULL, PANIC, pfree(), PGERROR_DEFAULT, PGERROR_VERBOSE, pgwin32_is_service(), ErrorData::sqlerrcode, unpack_sql_state(), WARNING, whereToSendOutput, write_console(), write_csvlog(), write_pipe_chunks(), and write_syslogger_file().
Referenced by EmitErrorReport().
{ StringInfoData buf; initStringInfo(&buf); formatted_log_time[0] = '\0'; log_line_prefix(&buf, edata); appendStringInfo(&buf, "%s: ", error_severity(edata->elevel)); if (Log_error_verbosity >= PGERROR_VERBOSE) appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode)); if (edata->message) append_with_tabs(&buf, edata->message); else append_with_tabs(&buf, _("missing error text")); if (edata->cursorpos > 0) appendStringInfo(&buf, _(" at character %d"), edata->cursorpos); else if (edata->internalpos > 0) appendStringInfo(&buf, _(" at character %d"), edata->internalpos); appendStringInfoChar(&buf, '\n'); if (Log_error_verbosity >= PGERROR_DEFAULT) { if (edata->detail_log) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("DETAIL: ")); append_with_tabs(&buf, edata->detail_log); appendStringInfoChar(&buf, '\n'); } else if (edata->detail) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("DETAIL: ")); append_with_tabs(&buf, edata->detail); appendStringInfoChar(&buf, '\n'); } if (edata->hint) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("HINT: ")); append_with_tabs(&buf, edata->hint); appendStringInfoChar(&buf, '\n'); } if (edata->internalquery) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("QUERY: ")); append_with_tabs(&buf, edata->internalquery); appendStringInfoChar(&buf, '\n'); } if (edata->context) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("CONTEXT: ")); append_with_tabs(&buf, edata->context); appendStringInfoChar(&buf, '\n'); } if (Log_error_verbosity >= PGERROR_VERBOSE) { /* assume no newlines in funcname or filename... */ if (edata->funcname && edata->filename) { log_line_prefix(&buf, edata); appendStringInfo(&buf, _("LOCATION: %s, %s:%d\n"), edata->funcname, edata->filename, edata->lineno); } else if (edata->filename) { log_line_prefix(&buf, edata); appendStringInfo(&buf, _("LOCATION: %s:%d\n"), edata->filename, edata->lineno); } } } /* * If the user wants the query that generated this error logged, do it. */ if (is_log_level_output(edata->elevel, log_min_error_statement) && debug_query_string != NULL && !edata->hide_stmt) { log_line_prefix(&buf, edata); appendStringInfoString(&buf, _("STATEMENT: ")); append_with_tabs(&buf, debug_query_string); appendStringInfoChar(&buf, '\n'); } #ifdef HAVE_SYSLOG /* Write to syslog, if enabled */ if (Log_destination & LOG_DESTINATION_SYSLOG) { int syslog_level; switch (edata->elevel) { case DEBUG5: case DEBUG4: case DEBUG3: case DEBUG2: case DEBUG1: syslog_level = LOG_DEBUG; break; case LOG: case COMMERROR: case INFO: syslog_level = LOG_INFO; break; case NOTICE: case WARNING: syslog_level = LOG_NOTICE; break; case ERROR: syslog_level = LOG_WARNING; break; case FATAL: syslog_level = LOG_ERR; break; case PANIC: default: syslog_level = LOG_CRIT; break; } write_syslog(syslog_level, buf.data); } #endif /* HAVE_SYSLOG */ #ifdef WIN32 /* Write to eventlog, if enabled */ if (Log_destination & LOG_DESTINATION_EVENTLOG) { write_eventlog(edata->elevel, buf.data, buf.len); } #endif /* WIN32 */ /* Write to stderr, if enabled */ if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == DestDebug) { /* * Use the chunking protocol if we know the syslogger should be * catching stderr output, and we are not ourselves the syslogger. * Otherwise, just do a vanilla write to stderr. */ if (redirection_done && !am_syslogger) write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_STDERR); #ifdef WIN32 /* * In a win32 service environment, there is no usable stderr. Capture * anything going there and write it to the eventlog instead. * * If stderr redirection is active, it was OK to write to stderr above * because that's really a pipe to the syslogger process. */ else if (pgwin32_is_service()) write_eventlog(edata->elevel, buf.data, buf.len); #endif else write_console(buf.data, buf.len); } /* If in the syslogger process, try to write messages direct to file */ if (am_syslogger) write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR); /* Write to CSV log if enabled */ if (Log_destination & LOG_DESTINATION_CSVLOG) { if (redirection_done || am_syslogger) { /* * send CSV data if it's safe to do so (syslogger doesn't need the * pipe). First get back the space in the message buffer. */ pfree(buf.data); write_csvlog(edata); } else { /* * syslogger not up (yet), so just dump the message to stderr, * unless we already did so above. */ if (!(Log_destination & LOG_DESTINATION_STDERR) && whereToSendOutput != DestDebug) write_console(buf.data, buf.len); pfree(buf.data); } } else { pfree(buf.data); } }
int set_errcontext_domain | ( | const char * | domain | ) |
Definition at line 1002 of file elog.c.
References CHECK_STACK_DEPTH, and ErrorData::context_domain.
{ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->context_domain = domain; return 0; /* return value does not matter */ }
static void set_errdata_field | ( | char ** | ptr, | |
const char * | str | |||
) | [static] |
Definition at line 1161 of file elog.c.
References Assert, ErrorContext, MemoryContextStrdup(), and NULL.
Referenced by err_generic_string().
{ Assert(*ptr == NULL); *ptr = MemoryContextStrdup(ErrorContext, str); }
static void setup_formatted_log_time | ( | void | ) | [static] |
Definition at line 1967 of file elog.c.
References FORMATTED_TS_LEN, gettimeofday(), log_timezone, NULL, pg_localtime(), and pg_strftime().
Referenced by log_line_prefix(), and write_csvlog().
{ struct timeval tv; pg_time_t stamp_time; char msbuf[8]; gettimeofday(&tv, NULL); stamp_time = (pg_time_t) tv.tv_sec; /* * Note: we expect that guc.c will ensure that log_timezone is set up (at * least with a minimal GMT value) before Log_line_prefix can become * nonempty or CSV mode can be selected. */ pg_strftime(formatted_log_time, FORMATTED_TS_LEN, /* leave room for milliseconds... */ "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&stamp_time, log_timezone)); /* 'paste' milliseconds into place... */ sprintf(msbuf, ".%03d", (int) (tv.tv_usec / 1000)); strncpy(formatted_log_time + 19, msbuf, 4); }
static void setup_formatted_start_time | ( | void | ) | [static] |
Definition at line 1995 of file elog.c.
References FORMATTED_TS_LEN, log_timezone, MyStartTime, pg_localtime(), and pg_strftime().
Referenced by log_line_prefix(), and write_csvlog().
{ pg_time_t stamp_time = (pg_time_t) MyStartTime; /* * Note: we expect that guc.c will ensure that log_timezone is set up (at * least with a minimal GMT value) before Log_line_prefix can become * nonempty or CSV mode can be selected. */ pg_strftime(formatted_start_time, FORMATTED_TS_LEN, "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&stamp_time, log_timezone)); }
int trace_recovery | ( | int | trace_level | ) |
Definition at line 3119 of file elog.c.
References LOG, and trace_recovery_messages.
Referenced by KnownAssignedXidsRemove(), KnownAssignedXidsRemovePreceding(), LogCurrentRunningXacts(), ProcArrayApplyRecoveryInfo(), ProcessCommittedInvalidationMessages(), RecordKnownAssignedTransactionIds(), RecoveryRestartPoint(), StandbyAcquireAccessExclusiveLock(), StandbyReleaseAllLocks(), StandbyReleaseLocks(), and StandbyReleaseOldLocks().
{ if (trace_level < LOG && trace_level >= trace_recovery_messages) return LOG; return trace_level; }
char* unpack_sql_state | ( | int | sql_state | ) |
Definition at line 2396 of file elog.c.
References PGUNSIXBIT.
Referenced by exec_stmt_block(), exec_stmt_getdiag(), exec_stmt_raise(), log_line_prefix(), PLy_generate_spi_exceptions(), send_message_to_server_log(), and write_csvlog().
{ static char buf[12]; int i; for (i = 0; i < 5; i++) { buf[i] = PGUNSIXBIT(sql_state); sql_state >>= 6; } buf[i] = '\0'; return buf; }
static const char * useful_strerror | ( | int | errnum | ) | [static] |
Definition at line 2932 of file elog.c.
References _, NULL, pgwin32_socket_strerror(), snprintf(), and strerror().
Referenced by expand_fmt_string().
{ /* this buffer is only used if errno has a bogus value */ static char errorstr_buf[48]; const char *str; #ifdef WIN32 /* Winsock error code range, per WinError.h */ if (errnum >= 10000 && errnum <= 11999) return pgwin32_socket_strerror(errnum); #endif str = strerror(errnum); /* * Some strerror()s return an empty string for out-of-range errno. This is * ANSI C spec compliant, but not exactly useful. */ if (str == NULL || *str == '\0') { snprintf(errorstr_buf, sizeof(errorstr_buf), /*------ translator: This string will be truncated at 47 characters expanded. */ _("operating system error %d"), errnum); str = errorstr_buf; } return str; }
static void write_console | ( | const char * | line, | |
int | len | |||
) | [static] |
Definition at line 1904 of file elog.c.
References CurrentMemoryContext, GetDatabaseEncoding(), GetPlatformEncoding(), in_error_recursion_trouble(), NULL, pfree(), and write.
Referenced by send_message_to_server_log(), and write_stderr().
{ int rc; #ifdef WIN32 /* * WriteConsoleW() will fail if stdout is redirected, so just fall through * to writing unconverted to the logfile in this case. * * Since we palloc the structure required for conversion, also fall * through to writing unconverted if we have not yet set up * CurrentMemoryContext. */ if (GetDatabaseEncoding() != GetPlatformEncoding() && !in_error_recursion_trouble() && !redirection_done && CurrentMemoryContext != NULL) { WCHAR *utf16; int utf16len; utf16 = pgwin32_toUTF16(line, len, &utf16len); if (utf16 != NULL) { HANDLE stdHandle; DWORD written; stdHandle = GetStdHandle(STD_ERROR_HANDLE); if (WriteConsoleW(stdHandle, utf16, utf16len, &written, NULL)) { pfree(utf16); return; } /* * In case WriteConsoleW() failed, fall back to writing the * message unconverted. */ pfree(utf16); } } #else /* * Conversion on non-win32 platforms is not implemented yet. It requires * non-throw version of pg_do_encoding_conversion(), that converts * unconvertable characters to '?' without errors. */ #endif /* * We ignore any error from write() here. We have no useful way to report * it ... certainly whining on stderr isn't likely to be productive. */ rc = write(fileno(stderr), line, len); (void) rc; }
static void write_csvlog | ( | ErrorData * | edata | ) | [static] |
Definition at line 2200 of file elog.c.
References am_syslogger, appendBinaryStringInfo(), appendCSVLiteral(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), application_name, PGPROC::backendId, ErrorData::context, ErrorData::cursorpos, StringInfoData::data, Port::database_name, debug_query_string, ErrorData::detail, ErrorData::detail_log, ErrorData::elevel, error_severity(), ErrorData::filename, ErrorData::funcname, get_ps_display(), GetTopTransactionIdIfAny(), ErrorData::hide_stmt, ErrorData::hint, initStringInfo(), ErrorData::internalpos, ErrorData::internalquery, InvalidBackendId, is_log_level_output(), StringInfoData::len, ErrorData::lineno, LOG_DESTINATION_CSVLOG, log_min_error_statement, PGPROC::lxid, ErrorData::message, MyProc, MyProcPid, MyProcPort, MyStartTime, NULL, pfree(), PGERROR_VERBOSE, Port::remote_host, Port::remote_port, setup_formatted_log_time(), setup_formatted_start_time(), ErrorData::sqlerrcode, unpack_sql_state(), Port::user_name, write_pipe_chunks(), and write_syslogger_file().
Referenced by send_message_to_server_log().
{ StringInfoData buf; bool print_stmt = false; /* static counter for line numbers */ static long log_line_number = 0; /* has counter been reset in current process? */ static int log_my_pid = 0; /* * This is one of the few places where we'd rather not inherit a static * variable's value from the postmaster. But since we will, reset it when * MyProcPid changes. */ if (log_my_pid != MyProcPid) { log_line_number = 0; log_my_pid = MyProcPid; formatted_start_time[0] = '\0'; } log_line_number++; initStringInfo(&buf); /* * timestamp with milliseconds * * Check if the timestamp is already calculated for the syslog message, * and use it if so. Otherwise, get the current timestamp. This is done * to put same timestamp in both syslog and csvlog messages. */ if (formatted_log_time[0] == '\0') setup_formatted_log_time(); appendStringInfoString(&buf, formatted_log_time); appendStringInfoChar(&buf, ','); /* username */ if (MyProcPort) appendCSVLiteral(&buf, MyProcPort->user_name); appendStringInfoChar(&buf, ','); /* database name */ if (MyProcPort) appendCSVLiteral(&buf, MyProcPort->database_name); appendStringInfoChar(&buf, ','); /* Process id */ if (MyProcPid != 0) appendStringInfo(&buf, "%d", MyProcPid); appendStringInfoChar(&buf, ','); /* Remote host and port */ if (MyProcPort && MyProcPort->remote_host) { appendStringInfoChar(&buf, '"'); appendStringInfoString(&buf, MyProcPort->remote_host); if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') { appendStringInfoChar(&buf, ':'); appendStringInfoString(&buf, MyProcPort->remote_port); } appendStringInfoChar(&buf, '"'); } appendStringInfoChar(&buf, ','); /* session id */ appendStringInfo(&buf, "%lx.%04x", (long) MyStartTime, MyProcPid); appendStringInfoChar(&buf, ','); /* Line number */ appendStringInfo(&buf, "%ld", log_line_number); appendStringInfoChar(&buf, ','); /* PS display */ if (MyProcPort) { StringInfoData msgbuf; const char *psdisp; int displen; initStringInfo(&msgbuf); psdisp = get_ps_display(&displen); appendBinaryStringInfo(&msgbuf, psdisp, displen); appendCSVLiteral(&buf, msgbuf.data); pfree(msgbuf.data); } appendStringInfoChar(&buf, ','); /* session start timestamp */ if (formatted_start_time[0] == '\0') setup_formatted_start_time(); appendStringInfoString(&buf, formatted_start_time); appendStringInfoChar(&buf, ','); /* Virtual transaction id */ /* keep VXID format in sync with lockfuncs.c */ if (MyProc != NULL && MyProc->backendId != InvalidBackendId) appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid); appendStringInfoChar(&buf, ','); /* Transaction id */ appendStringInfo(&buf, "%u", GetTopTransactionIdIfAny()); appendStringInfoChar(&buf, ','); /* Error severity */ appendStringInfoString(&buf, error_severity(edata->elevel)); appendStringInfoChar(&buf, ','); /* SQL state code */ appendStringInfoString(&buf, unpack_sql_state(edata->sqlerrcode)); appendStringInfoChar(&buf, ','); /* errmessage */ appendCSVLiteral(&buf, edata->message); appendStringInfoChar(&buf, ','); /* errdetail or errdetail_log */ if (edata->detail_log) appendCSVLiteral(&buf, edata->detail_log); else appendCSVLiteral(&buf, edata->detail); appendStringInfoChar(&buf, ','); /* errhint */ appendCSVLiteral(&buf, edata->hint); appendStringInfoChar(&buf, ','); /* internal query */ appendCSVLiteral(&buf, edata->internalquery); appendStringInfoChar(&buf, ','); /* if printed internal query, print internal pos too */ if (edata->internalpos > 0 && edata->internalquery != NULL) appendStringInfo(&buf, "%d", edata->internalpos); appendStringInfoChar(&buf, ','); /* errcontext */ appendCSVLiteral(&buf, edata->context); appendStringInfoChar(&buf, ','); /* user query --- only reported if not disabled by the caller */ if (is_log_level_output(edata->elevel, log_min_error_statement) && debug_query_string != NULL && !edata->hide_stmt) print_stmt = true; if (print_stmt) appendCSVLiteral(&buf, debug_query_string); appendStringInfoChar(&buf, ','); if (print_stmt && edata->cursorpos > 0) appendStringInfo(&buf, "%d", edata->cursorpos); appendStringInfoChar(&buf, ','); /* file error location */ if (Log_error_verbosity >= PGERROR_VERBOSE) { StringInfoData msgbuf; initStringInfo(&msgbuf); if (edata->funcname && edata->filename) appendStringInfo(&msgbuf, "%s, %s:%d", edata->funcname, edata->filename, edata->lineno); else if (edata->filename) appendStringInfo(&msgbuf, "%s:%d", edata->filename, edata->lineno); appendCSVLiteral(&buf, msgbuf.data); pfree(msgbuf.data); } appendStringInfoChar(&buf, ','); /* application name */ if (application_name) appendCSVLiteral(&buf, application_name); appendStringInfoChar(&buf, '\n'); /* If in the syslogger process, try to write messages direct to file */ if (am_syslogger) write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_CSVLOG); else write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_CSVLOG); pfree(buf.data); }
static void write_pipe_chunks | ( | char * | data, | |
int | len, | |||
int | dest | |||
) | [static] |
Definition at line 2642 of file elog.c.
References Assert, PipeProtoHeader::data, fd(), PipeProtoHeader::is_last, PipeProtoHeader::len, LOG_DESTINATION_CSVLOG, MyProcPid, PipeProtoHeader::nuls, PipeProtoHeader::pid, PIPE_HEADER_SIZE, PIPE_MAX_PAYLOAD, PipeProtoChunk::proto, and write.
Referenced by send_message_to_server_log(), and write_csvlog().
{ PipeProtoChunk p; int fd = fileno(stderr); int rc; Assert(len > 0); p.proto.nuls[0] = p.proto.nuls[1] = '\0'; p.proto.pid = MyProcPid; /* write all but the last chunk */ while (len > PIPE_MAX_PAYLOAD) { p.proto.is_last = (dest == LOG_DESTINATION_CSVLOG ? 'F' : 'f'); p.proto.len = PIPE_MAX_PAYLOAD; memcpy(p.proto.data, data, PIPE_MAX_PAYLOAD); rc = write(fd, &p, PIPE_HEADER_SIZE + PIPE_MAX_PAYLOAD); (void) rc; data += PIPE_MAX_PAYLOAD; len -= PIPE_MAX_PAYLOAD; } /* write the last chunk */ p.proto.is_last = (dest == LOG_DESTINATION_CSVLOG ? 'T' : 't'); p.proto.len = len; memcpy(p.proto.data, data, len); rc = write(fd, &p, PIPE_HEADER_SIZE + len); (void) rc; }
static void write_stderr | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 3037 of file elog.c.
References _, ERROR, pgwin32_is_service(), vsnprintf(), and write_console().
{ va_list ap; #ifdef WIN32 char errbuf[2048]; /* Arbitrary size? */ #endif fmt = _(fmt); va_start(ap, fmt); #ifndef WIN32 /* On Unix, we just fprintf to stderr */ vfprintf(stderr, fmt, ap); fflush(stderr); #else vsnprintf(errbuf, sizeof(errbuf), fmt, ap); /* * On Win32, we print to stderr if running on a console, or write to * eventlog if running as a service */ if (pgwin32_is_service()) /* Running as a service */ { write_eventlog(ERROR, errbuf, strlen(errbuf)); } else { /* Not running as service, write to stderr */ write_console(errbuf, strlen(errbuf)); fflush(stderr); } #endif va_end(ap); }
emit_log_hook_type emit_log_hook = NULL |
Definition at line 93 of file elog.c.
Referenced by _SPI_execute_plan(), _SPI_prepare_oneshot_plan(), _SPI_prepare_plan(), AutoVacLauncherMain(), BackgroundWriterMain(), cancel_parser_errposition_callback(), CheckpointerMain(), compile_plperl_function(), CopyFrom(), do_compile(), do_start_bgworker(), file_acquire_sample_rows(), fileIterateForeignScan(), FlushBuffer(), FlushRelationBuffers(), fmgr_sql(), fmgr_sql_validator(), inline_function(), inline_set_returning_function(), make_tuple_from_result_row(), parseTypeString(), plperl_func_handler(), plperl_inline_handler(), plperl_trigger_handler(), plpgsql_compile_inline(), plpgsql_exec_event_trigger(), plpgsql_exec_function(), plpgsql_exec_trigger(), plpython_call_handler(), plpython_inline_handler(), PLy_exec_function(), PLy_modify_tuple(), PostgresMain(), proc_exit_prepare(), setup_parser_errposition_callback(), SPI_cursor_open_internal(), SPI_plan_get_cached_plan(), StartupXLOG(), tsearch_readline_begin(), tsearch_readline_end(), and WalWriterMain().
int errordata_stack_depth = -1 [static] |
char formatted_log_time[FORMATTED_TS_LEN] [static] |
char formatted_start_time[FORMATTED_TS_LEN] [static] |
int Log_destination = LOG_DESTINATION_STDERR |
Definition at line 111 of file elog.c.
Referenced by assign_log_destination().
int Log_error_verbosity = PGERROR_VERBOSE |
char* Log_line_prefix = NULL |
sigjmp_buf* PG_exception_stack = NULL |
Definition at line 95 of file elog.c.
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWriterMain(), CheckpointerMain(), do_start_bgworker(), PostgresMain(), and WalWriterMain().
int recursion_depth = 0 [static] |
Definition at line 351 of file postmaster.c.
Referenced by SysLogger_Start(), and SysLoggerMain().
const char* save_format_domain [static] |
int save_format_errnumber [static] |