#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] |
1.7.1