Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite6c17c8

Browse files
committed
Fix possible crash during FATAL exit from reindexing.
index.c supposed that it could just use a PG_TRY block to clean up thestate associated with an active REINDEX operation. However, that codedoesn't run if we do a FATAL exit --- for example, due to a SIGTERMshutdown signal --- while the REINDEX is happening. And that state doesget consulted during catalog accesses, which makes it problematic if wedo any catalog accesses during shutdown --- for example, to clean up anytemp tables created in the session.If this combination of circumstances occurred, we could find ourselvestrying to access already-freed memory. In debug builds that'd fairlyreliably cause an assertion failure. In production we might oftenget away with it, but with some bad luck it could cause a core dump.Another possible bad outcome is an erroneous conclusion that anindex-to-be-accessed is being reindexed; but it looks like that wouldbe unlikely to have any consequences worse than failing to drop temptables right away. (They'd still get dropped by the next session thatuses that temp schema.)To fix, get rid of the use of PG_TRY here, and instead hook intothe transaction abort mechanisms to clean up reindex state.Per bug #16378 from Alexander Lakhin. This has been wrong for avery long time, so back-patch to all supported branches.Discussion:https://postgr.es/m/16378-7a70ca41b3ec2009@postgresql.org
1 parent0d0a0e4 commite6c17c8

File tree

3 files changed

+80
-71
lines changed

3 files changed

+80
-71
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include"access/xloginsert.h"
3232
#include"access/xlogutils.h"
3333
#include"catalog/catalog.h"
34+
#include"catalog/index.h"
3435
#include"catalog/namespace.h"
3536
#include"catalog/storage.h"
3637
#include"commands/async.h"
@@ -2577,6 +2578,9 @@ AbortTransaction(void)
25772578
*/
25782579
SetUserIdAndSecContext(s->prevUser,s->prevSecContext);
25792580

2581+
/* Forget about any active REINDEX. */
2582+
ResetReindexState(s->nestingLevel);
2583+
25802584
/* If in parallel mode, clean up workers and exit parallel mode. */
25812585
if (IsInParallelMode())
25822586
{
@@ -4684,6 +4688,9 @@ AbortSubTransaction(void)
46844688
*/
46854689
SetUserIdAndSecContext(s->prevUser,s->prevSecContext);
46864690

4691+
/* Forget about any active REINDEX. */
4692+
ResetReindexState(s->nestingLevel);
4693+
46874694
/* Exit from parallel mode, if necessary. */
46884695
if (IsInParallelMode())
46894696
{

‎src/backend/catalog/index.c

Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ static void SetReindexProcessing(Oid heapOid, Oid indexOid);
126126
staticvoidResetReindexProcessing(void);
127127
staticvoidSetReindexPending(List*indexes);
128128
staticvoidRemoveReindexPending(OidindexOid);
129-
staticvoidResetReindexPending(void);
130129

131130

132131
/*
@@ -3457,27 +3456,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
34573456
indexInfo->ii_ExclusionStrats=NULL;
34583457
}
34593458

3460-
/* ensure SetReindexProcessing state isn't leaked */
3461-
PG_TRY();
3462-
{
3463-
/* Suppress use of the target index while rebuilding it */
3464-
SetReindexProcessing(heapId,indexId);
3459+
/* Suppress use of the target index while rebuilding it */
3460+
SetReindexProcessing(heapId,indexId);
34653461

3466-
/* Create a new physical relation for the index */
3467-
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3468-
InvalidMultiXactId);
3462+
/* Create a new physical relation for the index */
3463+
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3464+
InvalidMultiXactId);
34693465

3470-
/* Initialize the index and rebuild */
3471-
/* Note: we do not need to re-establish pkey setting */
3472-
index_build(heapRelation,iRel,indexInfo, false, true);
3473-
}
3474-
PG_CATCH();
3475-
{
3476-
/* Make sure flag gets cleared on error exit */
3477-
ResetReindexProcessing();
3478-
PG_RE_THROW();
3479-
}
3480-
PG_END_TRY();
3466+
/* Initialize the index and rebuild */
3467+
/* Note: we do not need to re-establish pkey setting */
3468+
index_build(heapRelation,iRel,indexInfo, false, true);
3469+
3470+
/* Re-allow use of target index */
34813471
ResetReindexProcessing();
34823472

34833473
/*
@@ -3612,7 +3602,9 @@ reindex_relation(Oid relid, int flags, int options)
36123602
Relationrel;
36133603
Oidtoast_relid;
36143604
List*indexIds;
3605+
charpersistence;
36153606
boolresult;
3607+
ListCell*indexId;
36163608

36173609
/*
36183610
* Open and lock the relation. ShareLock is sufficient since we only need
@@ -3630,56 +3622,42 @@ reindex_relation(Oid relid, int flags, int options)
36303622
*/
36313623
indexIds=RelationGetIndexList(rel);
36323624

3633-
PG_TRY();
3625+
if (flags&REINDEX_REL_SUPPRESS_INDEX_USE)
36343626
{
3635-
ListCell*indexId;
3636-
charpersistence;
3637-
3638-
if (flags&REINDEX_REL_SUPPRESS_INDEX_USE)
3639-
{
3640-
/* Suppress use of all the indexes until they are rebuilt */
3641-
SetReindexPending(indexIds);
3642-
3643-
/*
3644-
* Make the new heap contents visible --- now things might be
3645-
* inconsistent!
3646-
*/
3647-
CommandCounterIncrement();
3648-
}
3627+
/* Suppress use of all the indexes until they are rebuilt */
3628+
SetReindexPending(indexIds);
36493629

36503630
/*
3651-
*Compute persistence of indexes: same as that of owning rel, unless
3652-
*caller specified otherwise.
3631+
*Make the new heap contents visible --- now things might be
3632+
*inconsistent!
36533633
*/
3654-
if (flags&REINDEX_REL_FORCE_INDEXES_UNLOGGED)
3655-
persistence=RELPERSISTENCE_UNLOGGED;
3656-
elseif (flags&REINDEX_REL_FORCE_INDEXES_PERMANENT)
3657-
persistence=RELPERSISTENCE_PERMANENT;
3658-
else
3659-
persistence=rel->rd_rel->relpersistence;
3634+
CommandCounterIncrement();
3635+
}
36603636

3661-
/* Reindex all the indexes. */
3662-
foreach(indexId,indexIds)
3663-
{
3664-
OidindexOid=lfirst_oid(indexId);
3637+
/*
3638+
* Compute persistence of indexes: same as that of owning rel, unless
3639+
* caller specified otherwise.
3640+
*/
3641+
if (flags&REINDEX_REL_FORCE_INDEXES_UNLOGGED)
3642+
persistence=RELPERSISTENCE_UNLOGGED;
3643+
elseif (flags&REINDEX_REL_FORCE_INDEXES_PERMANENT)
3644+
persistence=RELPERSISTENCE_PERMANENT;
3645+
else
3646+
persistence=rel->rd_rel->relpersistence;
36653647

3666-
reindex_index(indexOid, !(flags&REINDEX_REL_CHECK_CONSTRAINTS),
3667-
persistence,options);
3648+
/* Reindex all the indexes. */
3649+
foreach(indexId,indexIds)
3650+
{
3651+
OidindexOid=lfirst_oid(indexId);
36683652

3669-
CommandCounterIncrement();
3653+
reindex_index(indexOid, !(flags&REINDEX_REL_CHECK_CONSTRAINTS),
3654+
persistence,options);
36703655

3671-
/* Index should no longer be in the pending list */
3672-
Assert(!ReindexIsProcessingIndex(indexOid));
3673-
}
3674-
}
3675-
PG_CATCH();
3676-
{
3677-
/* Make sure list gets cleared on error exit */
3678-
ResetReindexPending();
3679-
PG_RE_THROW();
3656+
CommandCounterIncrement();
3657+
3658+
/* Index should no longer be in the pending list */
3659+
Assert(!ReindexIsProcessingIndex(indexOid));
36803660
}
3681-
PG_END_TRY();
3682-
ResetReindexPending();
36833661

36843662
/*
36853663
* Close rel, but continue to hold the lock.
@@ -3712,6 +3690,7 @@ reindex_relation(Oid relid, int flags, int options)
37123690
staticOidcurrentlyReindexedHeap=InvalidOid;
37133691
staticOidcurrentlyReindexedIndex=InvalidOid;
37143692
staticList*pendingReindexedIndexes=NIL;
3693+
staticintreindexingNestLevel=0;
37153694

37163695
/*
37173696
* ReindexIsProcessingHeap
@@ -3748,8 +3727,6 @@ ReindexIsProcessingIndex(Oid indexOid)
37483727
/*
37493728
* SetReindexProcessing
37503729
*Set flag that specified heap/index are being reindexed.
3751-
*
3752-
* NB: caller must use a PG_TRY block to ensure ResetReindexProcessing is done.
37533730
*/
37543731
staticvoid
37553732
SetReindexProcessing(OidheapOid,OidindexOid)
@@ -3762,6 +3739,8 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
37623739
currentlyReindexedIndex=indexOid;
37633740
/* Index is no longer "pending" reindex. */
37643741
RemoveReindexPending(indexOid);
3742+
/* This may have been set already, but in case it isn't, do so now. */
3743+
reindexingNestLevel=GetCurrentTransactionNestLevel();
37653744
}
37663745

37673746
/*
@@ -3773,14 +3752,14 @@ ResetReindexProcessing(void)
37733752
{
37743753
currentlyReindexedHeap=InvalidOid;
37753754
currentlyReindexedIndex=InvalidOid;
3755+
/* reindexingNestLevel remains set till end of (sub)transaction */
37763756
}
37773757

37783758
/*
37793759
* SetReindexPending
37803760
*Mark the given indexes as pending reindex.
37813761
*
3782-
* NB: caller must use a PG_TRY block to ensure ResetReindexPending is done.
3783-
* Also, we assume that the current memory context stays valid throughout.
3762+
* NB: we assume that the current memory context stays valid throughout.
37843763
*/
37853764
staticvoid
37863765
SetReindexPending(List*indexes)
@@ -3789,6 +3768,7 @@ SetReindexPending(List *indexes)
37893768
if (pendingReindexedIndexes)
37903769
elog(ERROR,"cannot reindex while reindexing");
37913770
pendingReindexedIndexes=list_copy(indexes);
3771+
reindexingNestLevel=GetCurrentTransactionNestLevel();
37923772
}
37933773

37943774
/*
@@ -3803,11 +3783,30 @@ RemoveReindexPending(Oid indexOid)
38033783
}
38043784

38053785
/*
3806-
*ResetReindexPending
3807-
*Unset reindex-pending status.
3786+
*ResetReindexState
3787+
*Clear all reindexing state during (sub)transaction abort.
38083788
*/
3809-
staticvoid
3810-
ResetReindexPending(void)
3789+
void
3790+
ResetReindexState(intnestLevel)
38113791
{
3812-
pendingReindexedIndexes=NIL;
3792+
/*
3793+
* Because reindexing is not re-entrant, we don't need to cope with nested
3794+
* reindexing states. We just need to avoid messing up the outer-level
3795+
* state in case a subtransaction fails within a REINDEX. So checking the
3796+
* current nest level against that of the reindex operation is sufficient.
3797+
*/
3798+
if (reindexingNestLevel >=nestLevel)
3799+
{
3800+
currentlyReindexedHeap=InvalidOid;
3801+
currentlyReindexedIndex=InvalidOid;
3802+
3803+
/*
3804+
* We needn't try to release the contents of pendingReindexedIndexes;
3805+
* that list should be in a transaction-lifespan context, so it will
3806+
* go away automatically.
3807+
*/
3808+
pendingReindexedIndexes=NIL;
3809+
3810+
reindexingNestLevel=0;
3811+
}
38133812
}

‎src/include/catalog/index.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
118118

119119
externvoidindex_set_state_flags(OidindexId,IndexStateFlagsActionaction);
120120

121+
externOidIndexGetRelation(OidindexId,boolmissing_ok);
122+
121123
externvoidreindex_index(OidindexId,boolskip_constraint_checks,
122124
charrelpersistence,intoptions);
123125

@@ -132,6 +134,7 @@ extern bool reindex_relation(Oid relid, int flags, int options);
132134

133135
externboolReindexIsProcessingHeap(OidheapOid);
134136
externboolReindexIsProcessingIndex(OidindexOid);
135-
externOidIndexGetRelation(OidindexId,boolmissing_ok);
137+
138+
externvoidResetReindexState(intnestLevel);
136139

137140
#endif/* INDEX_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp