Skip to content

Commit dbdf967

Browse files
committed
Use correct text domain for translating errcontext() messages.
errcontext() is typically used in an error context callback function, not within an ereport() invocation like e.g errmsg and errdetail are. That means that the message domain that the TEXTDOMAIN magic in ereport() determines is not the right one for the errcontext() calls. The message domain needs to be determined by the C file containing the errcontext() call, not the file containing the ereport() call. Fix by turning errcontext() into a macro that passes the TEXTDOMAIN to use for the errcontext message. "errcontext" was used in a few places as a variable or struct field name, I had to rename those out of the way, now that errcontext is a macro. We've had this problem all along, but this isn't doesn't seem worth backporting. It's a fairly minor issue, and turning errcontext from a function to a macro requires at least a recompile of any external code that calls errcontext().
1 parent c9d44a7 commit dbdf967

File tree

7 files changed

+82
-48
lines changed

7 files changed

+82
-48
lines changed

src/backend/access/transam/xlog.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -5698,7 +5698,7 @@ StartupXLOG(void)
56985698
bool recoveryContinue = true;
56995699
bool recoveryApply = true;
57005700
bool recoveryPause = false;
5701-
ErrorContextCallback errcontext;
5701+
ErrorContextCallback errcallback;
57025702
TimestampTz xtime;
57035703

57045704
InRedo = true;
@@ -5760,10 +5760,10 @@ StartupXLOG(void)
57605760
}
57615761

57625762
/* Setup error traceback support for ereport() */
5763-
errcontext.callback = rm_redo_error_callback;
5764-
errcontext.arg = (void *) record;
5765-
errcontext.previous = error_context_stack;
5766-
error_context_stack = &errcontext;
5763+
errcallback.callback = rm_redo_error_callback;
5764+
errcallback.arg = (void *) record;
5765+
errcallback.previous = error_context_stack;
5766+
error_context_stack = &errcallback;
57675767

57685768
/*
57695769
* ShmemVariableCache->nextXid must be beyond record's xid.
@@ -5808,7 +5808,7 @@ StartupXLOG(void)
58085808
RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
58095809

58105810
/* Pop the error context stack */
5811-
error_context_stack = errcontext.previous;
5811+
error_context_stack = errcallback.previous;
58125812

58135813
if (!XLogRecPtrIsInvalid(ControlFile->backupStartPoint) &&
58145814
XLByteLE(ControlFile->backupEndPoint, EndRecPtr))

src/backend/commands/copy.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -1901,7 +1901,7 @@ CopyFrom(CopyState cstate)
19011901
TupleTableSlot *myslot;
19021902
MemoryContext oldcontext = CurrentMemoryContext;
19031903

1904-
ErrorContextCallback errcontext;
1904+
ErrorContextCallback errcallback;
19051905
CommandId mycid = GetCurrentCommandId(true);
19061906
int hi_options = 0; /* start with default heap_insert options */
19071907
BulkInsertState bistate;
@@ -2046,10 +2046,10 @@ CopyFrom(CopyState cstate)
20462046
econtext = GetPerTupleExprContext(estate);
20472047

20482048
/* Set up callback to identify error line number */
2049-
errcontext.callback = CopyFromErrorCallback;
2050-
errcontext.arg = (void *) cstate;
2051-
errcontext.previous = error_context_stack;
2052-
error_context_stack = &errcontext;
2049+
errcallback.callback = CopyFromErrorCallback;
2050+
errcallback.arg = (void *) cstate;
2051+
errcallback.previous = error_context_stack;
2052+
error_context_stack = &errcallback;
20532053

20542054
for (;;)
20552055
{
@@ -2164,7 +2164,7 @@ CopyFrom(CopyState cstate)
21642164
nBufferedTuples, bufferedTuples);
21652165

21662166
/* Done, clean up */
2167-
error_context_stack = errcontext.previous;
2167+
error_context_stack = errcallback.previous;
21682168

21692169
FreeBulkInsertState(bistate);
21702170

src/backend/parser/parse_node.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ setup_parser_errposition_callback(ParseCallbackState *pcbstate,
145145
/* Setup error traceback support for ereport() */
146146
pcbstate->pstate = pstate;
147147
pcbstate->location = location;
148-
pcbstate->errcontext.callback = pcb_error_callback;
149-
pcbstate->errcontext.arg = (void *) pcbstate;
150-
pcbstate->errcontext.previous = error_context_stack;
151-
error_context_stack = &pcbstate->errcontext;
148+
pcbstate->errcallback.callback = pcb_error_callback;
149+
pcbstate->errcallback.arg = (void *) pcbstate;
150+
pcbstate->errcallback.previous = error_context_stack;
151+
error_context_stack = &pcbstate->errcallback;
152152
}
153153

154154
/*
@@ -158,7 +158,7 @@ void
158158
cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
159159
{
160160
/* Pop the error context stack */
161-
error_context_stack = pcbstate->errcontext.previous;
161+
error_context_stack = pcbstate->errcallback.previous;
162162
}
163163

164164
/*

src/backend/storage/buffer/bufmgr.c

+12-12
Original file line numberDiff line numberDiff line change
@@ -1888,7 +1888,7 @@ static void
18881888
FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
18891889
{
18901890
XLogRecPtr recptr;
1891-
ErrorContextCallback errcontext;
1891+
ErrorContextCallback errcallback;
18921892
instr_time io_start,
18931893
io_time;
18941894

@@ -1901,10 +1901,10 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
19011901
return;
19021902

19031903
/* Setup error traceback support for ereport() */
1904-
errcontext.callback = shared_buffer_write_error_callback;
1905-
errcontext.arg = (void *) buf;
1906-
errcontext.previous = error_context_stack;
1907-
error_context_stack = &errcontext;
1904+
errcallback.callback = shared_buffer_write_error_callback;
1905+
errcallback.arg = (void *) buf;
1906+
errcallback.previous = error_context_stack;
1907+
error_context_stack = &errcallback;
19081908

19091909
/* Find smgr relation for buffer */
19101910
if (reln == NULL)
@@ -1967,7 +1967,7 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
19671967
reln->smgr_rnode.node.relNode);
19681968

19691969
/* Pop the error context stack */
1970-
error_context_stack = errcontext.previous;
1970+
error_context_stack = errcallback.previous;
19711971
}
19721972

19731973
/*
@@ -2253,13 +2253,13 @@ FlushRelationBuffers(Relation rel)
22532253
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
22542254
(bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
22552255
{
2256-
ErrorContextCallback errcontext;
2256+
ErrorContextCallback errcallback;
22572257

22582258
/* Setup error traceback support for ereport() */
2259-
errcontext.callback = local_buffer_write_error_callback;
2260-
errcontext.arg = (void *) bufHdr;
2261-
errcontext.previous = error_context_stack;
2262-
error_context_stack = &errcontext;
2259+
errcallback.callback = local_buffer_write_error_callback;
2260+
errcallback.arg = (void *) bufHdr;
2261+
errcallback.previous = error_context_stack;
2262+
error_context_stack = &errcallback;
22632263

22642264
smgrwrite(rel->rd_smgr,
22652265
bufHdr->tag.forkNum,
@@ -2270,7 +2270,7 @@ FlushRelationBuffers(Relation rel)
22702270
bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
22712271

22722272
/* Pop the error context stack */
2273-
error_context_stack = errcontext.previous;
2273+
error_context_stack = errcallback.previous;
22742274
}
22752275
}
22762276

src/backend/utils/error/elog.c

+39-17
Original file line numberDiff line numberDiff line change
@@ -683,13 +683,13 @@ errcode_for_socket_access(void)
683683
* to the edata field because the buffer might be considerably larger than
684684
* really necessary.
685685
*/
686-
#define EVALUATE_MESSAGE(targetfield, appendval, translateit) \
686+
#define EVALUATE_MESSAGE(domain, targetfield, appendval, translateit) \
687687
{ \
688688
char *fmtbuf; \
689689
StringInfoData buf; \
690690
/* Internationalize the error format string */ \
691691
if (translateit && !in_error_recursion_trouble()) \
692-
fmt = dgettext(edata->domain, fmt); \
692+
fmt = dgettext((domain), fmt); \
693693
/* Expand %m in format string */ \
694694
fmtbuf = expand_fmt_string(fmt, edata); \
695695
initStringInfo(&buf); \
@@ -723,14 +723,14 @@ errcode_for_socket_access(void)
723723
* must be declared like "const char *fmt_singular, const char *fmt_plural,
724724
* unsigned long n, ...". Translation is assumed always wanted.
725725
*/
726-
#define EVALUATE_MESSAGE_PLURAL(targetfield, appendval) \
726+
#define EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval) \
727727
{ \
728728
const char *fmt; \
729729
char *fmtbuf; \
730730
StringInfoData buf; \
731731
/* Internationalize the error format string */ \
732732
if (!in_error_recursion_trouble()) \
733-
fmt = dngettext(edata->domain, fmt_singular, fmt_plural, n); \
733+
fmt = dngettext((domain), fmt_singular, fmt_plural, n); \
734734
else \
735735
fmt = (n == 1 ? fmt_singular : fmt_plural); \
736736
/* Expand %m in format string */ \
@@ -781,7 +781,7 @@ errmsg(const char *fmt,...)
781781
CHECK_STACK_DEPTH();
782782
oldcontext = MemoryContextSwitchTo(ErrorContext);
783783

784-
EVALUATE_MESSAGE(message, false, true);
784+
EVALUATE_MESSAGE(edata->domain, message, false, true);
785785

786786
MemoryContextSwitchTo(oldcontext);
787787
recursion_depth--;
@@ -810,7 +810,7 @@ errmsg_internal(const char *fmt,...)
810810
CHECK_STACK_DEPTH();
811811
oldcontext = MemoryContextSwitchTo(ErrorContext);
812812

813-
EVALUATE_MESSAGE(message, false, false);
813+
EVALUATE_MESSAGE(edata->domain, message, false, false);
814814

815815
MemoryContextSwitchTo(oldcontext);
816816
recursion_depth--;
@@ -833,7 +833,7 @@ errmsg_plural(const char *fmt_singular, const char *fmt_plural,
833833
CHECK_STACK_DEPTH();
834834
oldcontext = MemoryContextSwitchTo(ErrorContext);
835835

836-
EVALUATE_MESSAGE_PLURAL(message, false);
836+
EVALUATE_MESSAGE_PLURAL(edata->domain, message, false);
837837

838838
MemoryContextSwitchTo(oldcontext);
839839
recursion_depth--;
@@ -854,7 +854,7 @@ errdetail(const char *fmt,...)
854854
CHECK_STACK_DEPTH();
855855
oldcontext = MemoryContextSwitchTo(ErrorContext);
856856

857-
EVALUATE_MESSAGE(detail, false, true);
857+
EVALUATE_MESSAGE(edata->domain, detail, false, true);
858858

859859
MemoryContextSwitchTo(oldcontext);
860860
recursion_depth--;
@@ -881,7 +881,7 @@ errdetail_internal(const char *fmt,...)
881881
CHECK_STACK_DEPTH();
882882
oldcontext = MemoryContextSwitchTo(ErrorContext);
883883

884-
EVALUATE_MESSAGE(detail, false, false);
884+
EVALUATE_MESSAGE(edata->domain, detail, false, false);
885885

886886
MemoryContextSwitchTo(oldcontext);
887887
recursion_depth--;
@@ -902,7 +902,7 @@ errdetail_log(const char *fmt,...)
902902
CHECK_STACK_DEPTH();
903903
oldcontext = MemoryContextSwitchTo(ErrorContext);
904904

905-
EVALUATE_MESSAGE(detail_log, false, true);
905+
EVALUATE_MESSAGE(edata->domain, detail_log, false, true);
906906

907907
MemoryContextSwitchTo(oldcontext);
908908
recursion_depth--;
@@ -925,7 +925,7 @@ errdetail_plural(const char *fmt_singular, const char *fmt_plural,
925925
CHECK_STACK_DEPTH();
926926
oldcontext = MemoryContextSwitchTo(ErrorContext);
927927

928-
EVALUATE_MESSAGE_PLURAL(detail, false);
928+
EVALUATE_MESSAGE_PLURAL(edata->domain, detail, false);
929929

930930
MemoryContextSwitchTo(oldcontext);
931931
recursion_depth--;
@@ -946,7 +946,7 @@ errhint(const char *fmt,...)
946946
CHECK_STACK_DEPTH();
947947
oldcontext = MemoryContextSwitchTo(ErrorContext);
948948

949-
EVALUATE_MESSAGE(hint, false, true);
949+
EVALUATE_MESSAGE(edata->domain, hint, false, true);
950950

951951
MemoryContextSwitchTo(oldcontext);
952952
recursion_depth--;
@@ -955,14 +955,14 @@ errhint(const char *fmt,...)
955955

956956

957957
/*
958-
* errcontext --- add a context error message text to the current error
958+
* errcontext_msg --- add a context error message text to the current error
959959
*
960960
* Unlike other cases, multiple calls are allowed to build up a stack of
961961
* context information. We assume earlier calls represent more-closely-nested
962962
* states.
963963
*/
964964
int
965-
errcontext(const char *fmt,...)
965+
errcontext_msg(const char *fmt,...)
966966
{
967967
ErrorData *edata = &errordata[errordata_stack_depth];
968968
MemoryContext oldcontext;
@@ -971,13 +971,35 @@ errcontext(const char *fmt,...)
971971
CHECK_STACK_DEPTH();
972972
oldcontext = MemoryContextSwitchTo(ErrorContext);
973973

974-
EVALUATE_MESSAGE(context, true, true);
974+
EVALUATE_MESSAGE(edata->context_domain, context, true, true);
975975

976976
MemoryContextSwitchTo(oldcontext);
977977
recursion_depth--;
978978
return 0; /* return value does not matter */
979979
}
980980

981+
/*
982+
* set_errcontext_domain --- set message domain to be used by errcontext()
983+
*
984+
* errcontext_msg() can be called from a different module than the original
985+
* ereport(), so we cannot use the message domain passed in errstart() to
986+
* translate it. Instead, each errcontext_msg() call should be preceded by
987+
* a set_errcontext_domain() call to specify the domain. This is usually
988+
* done transparently by the errcontext() macro.
989+
*/
990+
int
991+
set_errcontext_domain(const char *domain)
992+
{
993+
ErrorData *edata = &errordata[errordata_stack_depth];
994+
995+
/* we don't bother incrementing recursion_depth */
996+
CHECK_STACK_DEPTH();
997+
998+
edata->context_domain = domain;
999+
1000+
return 0; /* return value does not matter */
1001+
}
1002+
9811003

9821004
/*
9831005
* errhidestmt --- optionally suppress STATEMENT: field of log entry
@@ -1201,7 +1223,7 @@ elog_finish(int elevel, const char *fmt,...)
12011223
recursion_depth++;
12021224
oldcontext = MemoryContextSwitchTo(ErrorContext);
12031225

1204-
EVALUATE_MESSAGE(message, false, false);
1226+
EVALUATE_MESSAGE(edata->domain, message, false, false);
12051227

12061228
MemoryContextSwitchTo(oldcontext);
12071229
recursion_depth--;
@@ -1260,7 +1282,7 @@ format_elog_string(const char *fmt,...)
12601282

12611283
oldcontext = MemoryContextSwitchTo(ErrorContext);
12621284

1263-
EVALUATE_MESSAGE(message, false, true);
1285+
EVALUATE_MESSAGE(edata->domain, message, false, true);
12641286

12651287
MemoryContextSwitchTo(oldcontext);
12661288

src/include/parser/parse_node.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ typedef struct ParseCallbackState
206206
{
207207
ParseState *pstate;
208208
int location;
209-
ErrorContextCallback errcontext;
209+
ErrorContextCallback errcallback;
210210
} ParseCallbackState;
211211

212212

src/include/utils/elog.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,19 @@ errhint(const char *fmt,...)
177177
the supplied arguments. */
178178
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
179179

180+
/*
181+
* errcontext() is typically called in error context callback functions, not
182+
* within an ereport() invocation. The callback function can be in a different
183+
* module than the ereport() call, so the message domain passed in errstart()
184+
* is not usually the correct domain for translating the context message.
185+
* set_errcontext_domain() first sets the domain to be used, and
186+
* errcontext_msg() passes the actual message.
187+
*/
188+
#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg
189+
190+
extern int set_errcontext_domain(const char *domain);
180191
extern int
181-
errcontext(const char *fmt,...)
192+
errcontext_msg(const char *fmt,...)
182193
/* This extension allows gcc to check the format string for consistency with
183194
the supplied arguments. */
184195
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
@@ -320,6 +331,7 @@ typedef struct ErrorData
320331
int lineno; /* __LINE__ of ereport() call */
321332
const char *funcname; /* __func__ of ereport() call */
322333
const char *domain; /* message domain */
334+
const char *context_domain; /* message domain for context message */
323335
int sqlerrcode; /* encoded ERRSTATE */
324336
char *message; /* primary error message */
325337
char *detail; /* detail error message */

0 commit comments

Comments
 (0)