@@ -341,6 +341,9 @@ static void CommitTransaction(void);
341
341
static TransactionId RecordTransactionAbort (bool isSubXact );
342
342
static void StartTransaction (void );
343
343
344
+ static void CommitTransactionCommandInternal (void );
345
+ static void AbortCurrentTransactionInternal (void );
346
+
344
347
static void StartSubTransaction (void );
345
348
static void CommitSubTransaction (void );
346
349
static void AbortSubTransaction (void );
@@ -3041,16 +3044,58 @@ RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
3041
3044
XactDeferrable = s -> save_XactDeferrable ;
3042
3045
}
3043
3046
3044
-
3045
3047
/*
3046
- * CommitTransactionCommand
3048
+ * CommitTransactionCommand -- a wrapper function handling the
3049
+ * loop over subtransactions to avoid a potentially dangerous recursion
3050
+ * in CommitTransactionCommandInternal().
3047
3051
*/
3048
3052
void
3049
3053
CommitTransactionCommand (void )
3054
+ {
3055
+ while (true)
3056
+ {
3057
+ switch (CurrentTransactionState -> blockState )
3058
+ {
3059
+ /*
3060
+ * The current already-failed subtransaction is ending due to
3061
+ * a ROLLBACK or ROLLBACK TO command, so pop it and
3062
+ * recursively examine the parent (which could be in any of
3063
+ * several states).
3064
+ */
3065
+ case TBLOCK_SUBABORT_END :
3066
+ CleanupSubTransaction ();
3067
+ continue ;
3068
+
3069
+ /*
3070
+ * As above, but it's not dead yet, so abort first.
3071
+ */
3072
+ case TBLOCK_SUBABORT_PENDING :
3073
+ AbortSubTransaction ();
3074
+ CleanupSubTransaction ();
3075
+ continue ;
3076
+ default :
3077
+ break ;
3078
+ }
3079
+ CommitTransactionCommandInternal ();
3080
+ break ;
3081
+ }
3082
+ }
3083
+
3084
+ /*
3085
+ * CommitTransactionCommandInternal - a function doing all the material work
3086
+ * regarding handling the commit transaction command except for loop over
3087
+ * subtransactions.
3088
+ */
3089
+ static void
3090
+ CommitTransactionCommandInternal (void )
3050
3091
{
3051
3092
TransactionState s = CurrentTransactionState ;
3052
3093
SavedTransactionCharacteristics savetc ;
3053
3094
3095
+ /* This states are handled in CommitTransactionCommand() */
3096
+ Assert (s -> blockState != TBLOCK_SUBABORT_END &&
3097
+ s -> blockState != TBLOCK_SUBABORT_PENDING );
3098
+
3054
3099
/* Must save in case we need to restore below */
3055
3100
SaveTransactionCharacteristics (& savetc );
3056
3101
@@ -3234,25 +3279,6 @@ CommitTransactionCommand(void)
3234
3279
BlockStateAsString (s -> blockState ));
3235
3280
break ;
3236
3281
3237
- /*
3238
- * The current already-failed subtransaction is ending due to a
3239
- * ROLLBACK or ROLLBACK TO command, so pop it and recursively
3240
- * examine the parent (which could be in any of several states).
3241
- */
3242
- case TBLOCK_SUBABORT_END :
3243
- CleanupSubTransaction ();
3244
- CommitTransactionCommand ();
3245
- break ;
3246
-
3247
- /*
3248
- * As above, but it's not dead yet, so abort first.
3249
- */
3250
- case TBLOCK_SUBABORT_PENDING :
3251
- AbortSubTransaction ();
3252
- CleanupSubTransaction ();
3253
- CommitTransactionCommand ();
3254
- break ;
3255
-
3256
3282
/*
3257
3283
* The current subtransaction is the target of a ROLLBACK TO
3258
3284
* command. Abort and pop it, then start a new subtransaction
@@ -3310,17 +3336,73 @@ CommitTransactionCommand(void)
3310
3336
s -> blockState = TBLOCK_SUBINPROGRESS ;
3311
3337
}
3312
3338
break ;
3339
+ default :
3340
+ /* Keep compiler quiet */
3341
+ break ;
3313
3342
}
3314
3343
}
3315
3344
3316
3345
/*
3317
- * AbortCurrentTransaction
3346
+ * AbortCurrentTransaction -- a wrapper function handling the
3347
+ * loop over subtransactions to avoid potentially dangerous recursion in
3348
+ * AbortCurrentTransactionInternal().
3318
3349
*/
3319
3350
void
3320
3351
AbortCurrentTransaction (void )
3352
+ {
3353
+ while (true)
3354
+ {
3355
+ switch (CurrentTransactionState -> blockState )
3356
+ {
3357
+ /*
3358
+ * If we failed while trying to create a subtransaction, clean
3359
+ * up the broken subtransaction and abort the parent. The
3360
+ * same applies if we get a failure while ending a
3361
+ * subtransaction.
3362
+ */
3363
+ case TBLOCK_SUBBEGIN :
3364
+ case TBLOCK_SUBRELEASE :
3365
+ case TBLOCK_SUBCOMMIT :
3366
+ case TBLOCK_SUBABORT_PENDING :
3367
+ case TBLOCK_SUBRESTART :
3368
+ AbortSubTransaction ();
3369
+ CleanupSubTransaction ();
3370
+ continue ;
3371
+
3372
+ /*
3373
+ * Same as above, except the Abort() was already done.
3374
+ */
3375
+ case TBLOCK_SUBABORT_END :
3376
+ case TBLOCK_SUBABORT_RESTART :
3377
+ CleanupSubTransaction ();
3378
+ continue ;
3379
+ default :
3380
+ break ;
3381
+ }
3382
+ AbortCurrentTransactionInternal ();
3383
+ break ;
3384
+ }
3385
+ }
3386
+
3387
+ /*
3388
+ * AbortCurrentTransactionInternal - a function doing all the material work
3389
+ * regarding handling the abort transaction command except for loop over
3390
+ * subtransactions.
3391
+ */
3392
+ static void
3393
+ AbortCurrentTransactionInternal (void )
3321
3394
{
3322
3395
TransactionState s = CurrentTransactionState ;
3323
3396
3397
+ /* This states are handled in AbortCurrentTransaction() */
3398
+ Assert (s -> blockState != TBLOCK_SUBBEGIN &&
3399
+ s -> blockState != TBLOCK_SUBRELEASE &&
3400
+ s -> blockState != TBLOCK_SUBCOMMIT &&
3401
+ s -> blockState != TBLOCK_SUBABORT_PENDING &&
3402
+ s -> blockState != TBLOCK_SUBRESTART &&
3403
+ s -> blockState != TBLOCK_SUBABORT_END &&
3404
+ s -> blockState != TBLOCK_SUBABORT_RESTART );
3405
+
3324
3406
switch (s -> blockState )
3325
3407
{
3326
3408
case TBLOCK_DEFAULT :
@@ -3441,29 +3523,8 @@ AbortCurrentTransaction(void)
3441
3523
AbortSubTransaction ();
3442
3524
s -> blockState = TBLOCK_SUBABORT ;
3443
3525
break ;
3444
-
3445
- /*
3446
- * If we failed while trying to create a subtransaction, clean up
3447
- * the broken subtransaction and abort the parent. The same
3448
- * applies if we get a failure while ending a subtransaction.
3449
- */
3450
- case TBLOCK_SUBBEGIN :
3451
- case TBLOCK_SUBRELEASE :
3452
- case TBLOCK_SUBCOMMIT :
3453
- case TBLOCK_SUBABORT_PENDING :
3454
- case TBLOCK_SUBRESTART :
3455
- AbortSubTransaction ();
3456
- CleanupSubTransaction ();
3457
- AbortCurrentTransaction ();
3458
- break ;
3459
-
3460
- /*
3461
- * Same as above, except the Abort() was already done.
3462
- */
3463
- case TBLOCK_SUBABORT_END :
3464
- case TBLOCK_SUBABORT_RESTART :
3465
- CleanupSubTransaction ();
3466
- AbortCurrentTransaction ();
3526
+ default :
3527
+ /* Keep compiler quiet */
3467
3528
break ;
3468
3529
}
3469
3530
}
0 commit comments