Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

elog.c File Reference

#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"
Include dependency graph for elog.c:

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)
ErrorDataCopyErrorData (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

ErrorContextCallbackerror_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 Documentation

#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 (  ) 
#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 
)
#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().


Function Documentation

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,
  ... 
)
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,
  ... 
)
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,
  ... 
)
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  ) 
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().

{
    if (elevel == LOG || elevel == COMMERROR)
    {
        if (log_min_level == LOG || log_min_level <= ERROR)
            return true;
    }
    else if (log_min_level == LOG)
    {
        /* elevel != LOG */
        if (elevel >= FATAL)
            return true;
    }
    /* Neither is LOG */
    else if (elevel >= log_min_level)
        return true;

    return false;
}

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  ) 
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);
}


Variable Documentation

Definition at line 106 of file elog.c.

ErrorData errordata[ERRORDATA_STACK_SIZE] [static]

Definition at line 143 of file elog.c.

int errordata_stack_depth = -1 [static]

Definition at line 145 of file elog.c.

char formatted_log_time[FORMATTED_TS_LEN] [static]

Definition at line 155 of file elog.c.

char formatted_start_time[FORMATTED_TS_LEN] [static]

Definition at line 154 of file elog.c.

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

Definition at line 109 of file elog.c.

char* Log_line_prefix = NULL

Definition at line 110 of file elog.c.

sigjmp_buf* PG_exception_stack = NULL
int recursion_depth = 0 [static]

Definition at line 147 of file elog.c.

Definition at line 351 of file postmaster.c.

Referenced by SysLogger_Start(), and SysLoggerMain().

const char* save_format_domain [static]

Definition at line 1322 of file elog.c.

int save_format_errnumber [static]

Definition at line 1321 of file elog.c.