Hi, hackers "The local variables that do not have the volatile type and have been changed between the setjmp() invocation and longjmp() call are indeterminate". This is what the POSIX (and C standard for setjmp) says.
That's fine actually, but if we put the PG_TRY()/CATCH() in a loop, high version gcc might complain. Version: $ gcc-9 --version gcc-9 (Ubuntu 9.1.0-2ubuntu2~19.04) 9.1.0 (Actually from gcc 7) Reproducer: ``` #include <setjmp.h> extern int other(void); extern void trigger(int *cond1); extern sigjmp_buf *PG_exception_stack; void trigger(int *cond1) { while (1) { if (*cond1 == 0) *cond1 = other(); while (*cond1) { sigjmp_buf *save_exception_stack = PG_exception_stack; sigjmp_buf local_sigjmp_buf; if (sigsetjmp(local_sigjmp_buf, 0) == 0) PG_exception_stack = &local_sigjmp_buf; else PG_exception_stack = (sigjmp_buf *) save_exception_stack; PG_exception_stack = (sigjmp_buf *) save_exception_stack; } } } ``` ``` $ gcc-9 -O1 -Werror=uninitialized -fexpensive-optimizations -ftree-pre -c -o /dev/null reproducer.c reproducer.c: In function 'trigger': reproducer.c:17:16: error: 'save_exception_stack' is used uninitialized in this function [-Werror=uninitialized] 17 | sigjmp_buf *save_exception_stack = PG_exception_stack; | ^~~~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors ``` Codes re-ordering matters, when it warns: ``` sigjmp_buf *save_exception_stack = PG_exception_stack; 2f: 48 8b 1d 00 00 00 00 mov 0x0(%rip),%rbx # 36 <trigger+0x36> 36: 48 89 5c 24 18 mov %rbx,0x18(%rsp) sigjmp_buf local_sigjmp_buf; if (sigsetjmp(local_sigjmp_buf, 0) == 0) ``` When it doesn't complain: ``` sigjmp_buf *save_exception_stack = PG_exception_stack; sigjmp_buf local_sigjmp_buf; if (sigsetjmp(local_sigjmp_buf, 0) == 0) 29: 48 8d 44 24 20 lea 0x20(%rsp),%rax 2e: 48 89 44 24 08 mov %rax,0x8(%rsp) ... sigjmp_buf *save_exception_stack = PG_exception_stack; 3c: 48 8b 1d 00 00 00 00 mov 0x0(%rip),%rbx # 43 <trigger+0x43> 43: 48 89 5c 24 18 mov %rbx,0x18(%rsp) ``` Greenplum had an issue reporting save_exception_stack and save_context_stack not initialized. https://github.com/greenplum-db/gpdb/issues/8262 I filed a bug report for gcc, they think it's expected. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91395 Since high version gcc thinks it's supposed to report warning, we need to make these two variables volatile? Or have I missed something? -- Adam Lee
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index dbfd8efd26..97e8405bfa 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -300,8 +300,8 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; */ #define PG_TRY() \ do { \ - sigjmp_buf *save_exception_stack = PG_exception_stack; \ - ErrorContextCallback *save_context_stack = error_context_stack; \ + sigjmp_buf * volatile save_exception_stack = PG_exception_stack; \ + ErrorContextCallback * volatile save_context_stack = error_context_stack; \ sigjmp_buf local_sigjmp_buf; \ if (sigsetjmp(local_sigjmp_buf, 0) == 0) \ { \