Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8305629

Browse files
committed
Minor code refactoring in elog.c (no functional change).
Combine some duplicated code stanzas by creating small functions.Most of these duplications arose at a time when I wouldn't havetrusted C compilers to auto-inline small functions intelligently,but they're probably poor practice now. Similarly split out somebits that aren't actually duplicative as the code stands, but wouldbecome so after an upcoming patch to add another error-handlingcode path.Take the opportunity to add some lengthier comments about whatwe're doing here, too. Re-order one function that seemed notvery well-placed.Patch by me, per suggestions from Andres Freund.Discussion:https://postgr.es/m/3bbbb0df-7382-bf87-9737-340ba096e034@postgrespro.ru
1 parent3b31821 commit8305629

File tree

1 file changed

+141
-116
lines changed

1 file changed

+141
-116
lines changed

‎src/backend/utils/error/elog.c

Lines changed: 141 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,15 @@ static char formatted_log_time[FORMATTED_TS_LEN];
176176

177177

178178
staticconstchar*err_gettext(constchar*str)pg_attribute_format_arg(1);
179+
staticErrorData*get_error_stack_entry(void);
180+
staticvoidset_stack_entry_domain(ErrorData*edata,constchar*domain);
181+
staticvoidset_stack_entry_location(ErrorData*edata,
182+
constchar*filename,intlineno,
183+
constchar*funcname);
184+
staticboolmatches_backtrace_functions(constchar*funcname);
179185
staticpg_noinlinevoidset_backtrace(ErrorData*edata,intnum_skip);
180186
staticvoidset_errdata_field(MemoryContextData*cxt,char**ptr,constchar*str);
187+
staticvoidFreeErrorDataContents(ErrorData*edata);
181188
staticvoidwrite_console(constchar*line,intlen);
182189
staticconstchar*process_log_prefix_padding(constchar*p,int*ppadding);
183190
staticvoidlog_line_prefix(StringInfobuf,ErrorData*edata);
@@ -434,36 +441,20 @@ errstart(int elevel, const char *domain)
434441
debug_query_string=NULL;
435442
}
436443
}
437-
if (++errordata_stack_depth >=ERRORDATA_STACK_SIZE)
438-
{
439-
/*
440-
* Wups, stack not big enough. We treat this as a PANIC condition
441-
* because it suggests an infinite loop of errors during error
442-
* recovery.
443-
*/
444-
errordata_stack_depth=-1;/* make room on stack */
445-
ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
446-
}
447444

448445
/* Initialize data for this error frame */
449-
edata=&errordata[errordata_stack_depth];
450-
MemSet(edata,0,sizeof(ErrorData));
446+
edata=get_error_stack_entry();
451447
edata->elevel=elevel;
452448
edata->output_to_server=output_to_server;
453449
edata->output_to_client=output_to_client;
454-
/* the default text domain is the backend's */
455-
edata->domain=domain ?domain :PG_TEXTDOMAIN("postgres");
456-
/* initialize context_domain the same way (see set_errcontext_domain()) */
457-
edata->context_domain=edata->domain;
450+
set_stack_entry_domain(edata,domain);
458451
/* Select default errcode based on elevel */
459452
if (elevel >=ERROR)
460453
edata->sqlerrcode=ERRCODE_INTERNAL_ERROR;
461454
elseif (elevel >=WARNING)
462455
edata->sqlerrcode=ERRCODE_WARNING;
463456
else
464457
edata->sqlerrcode=ERRCODE_SUCCESSFUL_COMPLETION;
465-
/* errno is saved here so that error parameter eval can't change it */
466-
edata->saved_errno=errno;
467458

468459
/*
469460
* Any allocations for this error state level should go into ErrorContext
@@ -474,32 +465,6 @@ errstart(int elevel, const char *domain)
474465
return true;
475466
}
476467

477-
/*
478-
* Checks whether the given funcname matches backtrace_functions; see
479-
* check_backtrace_functions.
480-
*/
481-
staticbool
482-
matches_backtrace_functions(constchar*funcname)
483-
{
484-
char*p;
485-
486-
if (!backtrace_symbol_list||funcname==NULL||funcname[0]=='\0')
487-
return false;
488-
489-
p=backtrace_symbol_list;
490-
for (;;)
491-
{
492-
if (*p=='\0')/* end of backtrace_symbol_list */
493-
break;
494-
495-
if (strcmp(funcname,p)==0)
496-
return true;
497-
p+=strlen(p)+1;
498-
}
499-
500-
return false;
501-
}
502-
503468
/*
504469
* errfinish --- end an error-reporting cycle
505470
*
@@ -520,23 +485,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
520485
CHECK_STACK_DEPTH();
521486

522487
/* Save the last few bits of error state into the stack entry */
523-
if (filename)
524-
{
525-
constchar*slash;
526-
527-
/* keep only base name, useful especially for vpath builds */
528-
slash=strrchr(filename,'/');
529-
if (slash)
530-
filename=slash+1;
531-
/* Some Windows compilers use backslashes in __FILE__ strings */
532-
slash=strrchr(filename,'\\');
533-
if (slash)
534-
filename=slash+1;
535-
}
536-
537-
edata->filename=filename;
538-
edata->lineno=lineno;
539-
edata->funcname=funcname;
488+
set_stack_entry_location(edata,filename,lineno,funcname);
540489

541490
elevel=edata->elevel;
542491

@@ -546,6 +495,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
546495
*/
547496
oldcontext=MemoryContextSwitchTo(ErrorContext);
548497

498+
/* Collect backtrace, if enabled and we didn't already */
549499
if (!edata->backtrace&&
550500
edata->funcname&&
551501
backtrace_functions&&
@@ -596,31 +546,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
596546
EmitErrorReport();
597547

598548
/* Now free up subsidiary data attached to stack entry, and release it */
599-
if (edata->message)
600-
pfree(edata->message);
601-
if (edata->detail)
602-
pfree(edata->detail);
603-
if (edata->detail_log)
604-
pfree(edata->detail_log);
605-
if (edata->hint)
606-
pfree(edata->hint);
607-
if (edata->context)
608-
pfree(edata->context);
609-
if (edata->backtrace)
610-
pfree(edata->backtrace);
611-
if (edata->schema_name)
612-
pfree(edata->schema_name);
613-
if (edata->table_name)
614-
pfree(edata->table_name);
615-
if (edata->column_name)
616-
pfree(edata->column_name);
617-
if (edata->datatype_name)
618-
pfree(edata->datatype_name);
619-
if (edata->constraint_name)
620-
pfree(edata->constraint_name);
621-
if (edata->internalquery)
622-
pfree(edata->internalquery);
623-
549+
FreeErrorDataContents(edata);
624550
errordata_stack_depth--;
625551

626552
/* Exit error-handling context */
@@ -685,6 +611,120 @@ errfinish(const char *filename, int lineno, const char *funcname)
685611
CHECK_FOR_INTERRUPTS();
686612
}
687613

614+
/*
615+
* get_error_stack_entry --- allocate and initialize a new stack entry
616+
*
617+
* The entry should be freed, when we're done with it, by calling
618+
* FreeErrorDataContents() and then decrementing errordata_stack_depth.
619+
*
620+
* Returning the entry's address is just a notational convenience,
621+
* since it had better be errordata[errordata_stack_depth].
622+
*
623+
* Although the error stack is not large, we don't expect to run out of space.
624+
* Using more than one entry implies a new error report during error recovery,
625+
* which is possible but already suggests we're in trouble. If we exhaust the
626+
* stack, almost certainly we are in an infinite loop of errors during error
627+
* recovery, so we give up and PANIC.
628+
*
629+
* (Note that this is distinct from the recursion_depth checks, which
630+
* guard against recursion while handling a single stack entry.)
631+
*/
632+
staticErrorData*
633+
get_error_stack_entry(void)
634+
{
635+
ErrorData*edata;
636+
637+
/* Allocate error frame */
638+
errordata_stack_depth++;
639+
if (unlikely(errordata_stack_depth >=ERRORDATA_STACK_SIZE))
640+
{
641+
/* Wups, stack not big enough */
642+
errordata_stack_depth=-1;/* make room on stack */
643+
ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
644+
}
645+
646+
/* Initialize error frame to all zeroes/NULLs */
647+
edata=&errordata[errordata_stack_depth];
648+
memset(edata,0,sizeof(ErrorData));
649+
650+
/* Save errno immediately to ensure error parameter eval can't change it */
651+
edata->saved_errno=errno;
652+
653+
returnedata;
654+
}
655+
656+
/*
657+
* set_stack_entry_domain --- fill in the internationalization domain
658+
*/
659+
staticvoid
660+
set_stack_entry_domain(ErrorData*edata,constchar*domain)
661+
{
662+
/* the default text domain is the backend's */
663+
edata->domain=domain ?domain :PG_TEXTDOMAIN("postgres");
664+
/* initialize context_domain the same way (see set_errcontext_domain()) */
665+
edata->context_domain=edata->domain;
666+
}
667+
668+
/*
669+
* set_stack_entry_location --- fill in code-location details
670+
*
671+
* Store the values of __FILE__, __LINE__, and __func__ from the call site.
672+
* We make an effort to normalize __FILE__, since compilers are inconsistent
673+
* about how much of the path they'll include, and we'd prefer that the
674+
* behavior not depend on that (especially, that it not vary with build path).
675+
*/
676+
staticvoid
677+
set_stack_entry_location(ErrorData*edata,
678+
constchar*filename,intlineno,
679+
constchar*funcname)
680+
{
681+
if (filename)
682+
{
683+
constchar*slash;
684+
685+
/* keep only base name, useful especially for vpath builds */
686+
slash=strrchr(filename,'/');
687+
if (slash)
688+
filename=slash+1;
689+
/* Some Windows compilers use backslashes in __FILE__ strings */
690+
slash=strrchr(filename,'\\');
691+
if (slash)
692+
filename=slash+1;
693+
}
694+
695+
edata->filename=filename;
696+
edata->lineno=lineno;
697+
edata->funcname=funcname;
698+
}
699+
700+
/*
701+
* matches_backtrace_functions --- checks whether the given funcname matches
702+
* backtrace_functions
703+
*
704+
* See check_backtrace_functions.
705+
*/
706+
staticbool
707+
matches_backtrace_functions(constchar*funcname)
708+
{
709+
constchar*p;
710+
711+
if (!backtrace_symbol_list||funcname==NULL||funcname[0]=='\0')
712+
return false;
713+
714+
p=backtrace_symbol_list;
715+
for (;;)
716+
{
717+
if (*p=='\0')/* end of backtrace_symbol_list */
718+
break;
719+
720+
if (strcmp(funcname,p)==0)
721+
return true;
722+
p+=strlen(p)+1;
723+
}
724+
725+
return false;
726+
}
727+
688728

689729
/*
690730
* errcode --- add SQLSTATE error code to the current error
@@ -1611,6 +1651,18 @@ CopyErrorData(void)
16111651
*/
16121652
void
16131653
FreeErrorData(ErrorData*edata)
1654+
{
1655+
FreeErrorDataContents(edata);
1656+
pfree(edata);
1657+
}
1658+
1659+
/*
1660+
* FreeErrorDataContents --- free the subsidiary data of an ErrorData.
1661+
*
1662+
* This can be used on either an error stack entry or a copied ErrorData.
1663+
*/
1664+
staticvoid
1665+
FreeErrorDataContents(ErrorData*edata)
16141666
{
16151667
if (edata->message)
16161668
pfree(edata->message);
@@ -1636,7 +1688,6 @@ FreeErrorData(ErrorData *edata)
16361688
pfree(edata->constraint_name);
16371689
if (edata->internalquery)
16381690
pfree(edata->internalquery);
1639-
pfree(edata);
16401691
}
16411692

16421693
/*
@@ -1742,18 +1793,7 @@ ReThrowError(ErrorData *edata)
17421793
recursion_depth++;
17431794
MemoryContextSwitchTo(ErrorContext);
17441795

1745-
if (++errordata_stack_depth >=ERRORDATA_STACK_SIZE)
1746-
{
1747-
/*
1748-
* Wups, stack not big enough. We treat this as a PANIC condition
1749-
* because it suggests an infinite loop of errors during error
1750-
* recovery.
1751-
*/
1752-
errordata_stack_depth=-1;/* make room on stack */
1753-
ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
1754-
}
1755-
1756-
newedata=&errordata[errordata_stack_depth];
1796+
newedata=get_error_stack_entry();
17571797
memcpy(newedata,edata,sizeof(ErrorData));
17581798

17591799
/* Make copies of separately-allocated fields */
@@ -1854,26 +1894,11 @@ GetErrorContextStack(void)
18541894
ErrorContextCallback*econtext;
18551895

18561896
/*
1857-
*Okay, crank up a stack entry to store the info in.
1897+
*Crank up a stack entry to store the info in.
18581898
*/
18591899
recursion_depth++;
18601900

1861-
if (++errordata_stack_depth >=ERRORDATA_STACK_SIZE)
1862-
{
1863-
/*
1864-
* Wups, stack not big enough. We treat this as a PANIC condition
1865-
* because it suggests an infinite loop of errors during error
1866-
* recovery.
1867-
*/
1868-
errordata_stack_depth=-1;/* make room on stack */
1869-
ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
1870-
}
1871-
1872-
/*
1873-
* Things look good so far, so initialize our error frame
1874-
*/
1875-
edata=&errordata[errordata_stack_depth];
1876-
MemSet(edata,0,sizeof(ErrorData));
1901+
edata=get_error_stack_entry();
18771902

18781903
/*
18791904
* Set up assoc_context to be the caller's context, so any allocations

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp