Hello, postgresmen!
I found incorrect execution of ereport() macro.
If we pass into ereport() function 2 or more arguments, the macro errcontext does not correct execute. So, ereport() call stack is:
If we pass into ereport() function 2 or more arguments, the macro errcontext does not correct execute. So, ereport() call stack is:
errstart
errcontext_msg
set_errcontext_domain
errmsg
errfinish
pg_unreachable
errcontext_msg
set_errcontext_domain
errmsg
errfinish
pg_unreachable
This bug causes that error messages (for example, in PL/TCL) are not localized.
Solutions:
- Wrap all errcontext() macro in brackets, that is errcontext("error message %s", "end message") -> (errcontext("error message %s", "end message"))
Solutions:
- Wrap all errcontext() macro in brackets, that is errcontext("error message %s", "end message") -> (errcontext("error message %s", "end message"))
- Rewrite this macro
- ???
I am attaching to this letter a test case that shows the behavior errcontext() macro and the way to fix it.
I am using postgresql 9.4 and test it on gcc 4.7 and gcc 4.8.1.
-- Best regards, Dmitry Voronin
#include <stdio.h> #define ereport_domain(elevel, domain, rest) \ do { \ const int elevel_ = (elevel); \ if (errstart(elevel_, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain)) \ errfinish rest; \ if (elevel_ >= 2) \ pg_unreachable(); \ } while(0)
#define ereport(elevel, rest) \ ereport_domain(elevel, TEXTDOMAIN, rest) #define TEXTDOMAIN NULL #define PG_FUNCNAME_MACRO NULL #define ERROR 20 #define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg int set_errcontext_domain(const char *domain) { printf("set_errcontext_domain\n"); } int errstart(int elevel, const char *filename, int lineno, const char *funcname, const char *domain) { printf("errstart\n"); return 1; } void pg_unreachable() { printf("pg_unreachable\n"); } void errfinish(int dummy, ...) { printf("errfinish\n"); } int errcontext_msg(const char *fmt,...) { printf("errcontext_msg\n"); return 0; } int errmsg(const char *fmt, ...) { printf("errmsg\n"); return 0; } int main() { /* this is incorrect */ ereport(ERROR, (errmsg("%s", "error message"), errcontext("%s\nin PL/Tcl function \"%s\"", "test1", "test2"))); printf("\n"); /* this is correct */ ereport(ERROR, (errmsg("%s", "error message"), (errcontext("%s\nin PL/Tcl function \"%s\"", "test1", "test2")))); return 0; }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers