try/catch macros for Postgres backend - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | try/catch macros for Postgres backend |
Date | |
Msg-id | 1222.1091060357@sss.pgh.pa.us Whole thread Raw |
Responses |
Re: try/catch macros for Postgres backend
Re: try/catch macros for Postgres backend Re: try/catch macros for Postgres backend Re: try/catch macros for Postgres backend Re: try/catch macros for Postgres backend |
List | pgsql-hackers |
In service of the refactoring of error handling that I was talking about a few days ago, I'm finding that there are several places that really ought to catch longjmps and clean up after themselves, instead of expecting that whatever mess they've made will be cleaned up for them when control gets back to PostgresMain(). If we have functions that can catch errors, control might *not* go right back to PostgresMain(), and so throwing random cleanup actions into the sigsetjmp branch there is No Good. This is no big deal since pltcl and plpython already do much the same thing, but I'm starting to think that instead of directly hacking on Warn_restart, it would be good to have some macros hiding the details. The syntax I'm toying with is PG_TRY();{ ... code that might elog ...}PG_CATCH();{ ... recovery code here ... PG_RE_THROW(); // optional}PG_END_CATCH(); The braces in this are not actually necessary, but will be good style since they help visually set off the controlled code. (You can't just indent the controlled code without adding braces, because pg_indent will helpfully undo it.) This would expand to something on the close order of do { sigjmp_buf local_save_restart; memcpy(local_save_restart, Warn_restart, sizeof()); if (sigsetjmp(warn_restart) == 0) { ... code that mightelog ... memcpy(Warn_restart, local_save_restart, sizeof()); } else { memcpy(Warn_restart, local_save_restart,sizeof()); ... recovery code here ... } } while(0) and of course PG_RE_THROW is just a siglongjmp call. Does anyone have a problem with this macro syntax? The try/catch names are stolen from Java, so I'm figuring they won't terribly surprise any modern programmer, but I'm open to different names if anyone has a better idea. Also, the memcpy technique for saving/restoring Warn_restart is what pltcl and plpython currently use, and it works, but it seems unnecessarily inefficient. A further improvement would be to replace Warn_restart by a pointer defined likeextern sigjmp_buf *exception_stack_top; and then the macro expansion would be something more like do { sigjmp_buf *save_exception_stack = exception_stack_top; sigjmp_buf local_sigjmp_buf; if (sigsetjmp(local_sigjmp_buf) == 0) { exception_stack_top = &local_sigjmp_buf; ... code that mightelog ... exception_stack_top = save_exception_stack; } else { exception_stack_top = save_exception_stack; ... recovery code here ... } } while(0) while elog.c and PG_RE_THROW would need to dosiglongjmp(*exception_stack_top, 1); I think that this should work but does anyone know of any machines where it would have portability issues? regards, tom lane
pgsql-hackers by date: