diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-01-24 21:49:17 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-01-24 21:49:17 +0000 |
commit | 875353b99f64550c2fee1a3a8e3491e69decd9c7 (patch) | |
tree | 4d89f17c837687a71c56791d9be93fab69630bec /src/backend/commands/trigger.c | |
parent | 74f4be6c04933aafb9a7939c6c3f841052b49608 (diff) | |
download | postgresql-875353b99f64550c2fee1a3a8e3491e69decd9c7.tar.gz postgresql-875353b99f64550c2fee1a3a8e3491e69decd9c7.zip |
Fix assorted core dumps and Assert failures that could occur during
AbortTransaction or AbortSubTransaction, when trying to clean up after an
error that prevented (sub)transaction start from completing:
* access to TopTransactionResourceOwner that might not exist
* assert failure in AtEOXact_GUC, if AtStart_GUC not called yet
* assert failure or core dump in AfterTriggerEndSubXact, if
AfterTriggerBeginSubXact not called yet
Per testing by injecting elog(ERROR) at successive steps in StartTransaction
and StartSubTransaction. It's not clear whether all of these cases could
really occur in the field, but at least one of them is easily exposed by
simple stress testing, as per my accidental discovery yesterday.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index e585f1517ad..cec815cf608 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.259 2010/01/17 22:56:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.260 2010/01/24 21:49:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3690,10 +3690,9 @@ AfterTriggerEndSubXact(bool isCommit) /* * Pop the prior state if needed. */ - Assert(my_level < afterTriggers->maxtransdepth); - if (isCommit) { + Assert(my_level < afterTriggers->maxtransdepth); /* If we saved a prior state, we don't need it anymore */ state = afterTriggers->state_stack[my_level]; if (state != NULL) @@ -3706,8 +3705,16 @@ AfterTriggerEndSubXact(bool isCommit) else { /* - * Aborting. Release any event lists from queries being aborted, and - * restore query_depth to its pre-subxact value. + * Aborting. It is possible subxact start failed before calling + * AfterTriggerBeginSubXact, in which case we mustn't risk touching + * stack levels that aren't there. + */ + if (my_level >= afterTriggers->maxtransdepth) + return; + + /* + * Release any event lists from queries being aborted, and restore + * query_depth to its pre-subxact value. */ while (afterTriggers->query_depth > afterTriggers->depth_stack[my_level]) { |