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

Commit56259c3

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 parent6ab98db commit56259c3

File tree

3 files changed

+82
-73
lines changed

3 files changed

+82
-73
lines changed

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

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

2580+
/* Forget about any active REINDEX. */
2581+
ResetReindexState(s->nestingLevel);
2582+
25792583
/* If in parallel mode, clean up workers and exit parallel mode. */
25802584
if (IsInParallelMode())
25812585
{
@@ -4785,6 +4789,9 @@ AbortSubTransaction(void)
47854789
*/
47864790
SetUserIdAndSecContext(s->prevUser,s->prevSecContext);
47874791

4792+
/* Forget about any active REINDEX. */
4793+
ResetReindexState(s->nestingLevel);
4794+
47884795
/* Exit from parallel mode, if necessary. */
47894796
if (IsInParallelMode())
47904797
{

‎src/backend/catalog/index.c

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ static void SetReindexProcessing(Oid heapOid, Oid indexOid);
144144
staticvoidResetReindexProcessing(void);
145145
staticvoidSetReindexPending(List*indexes);
146146
staticvoidRemoveReindexPending(OidindexOid);
147-
staticvoidResetReindexPending(void);
148147

149148

150149
/*
@@ -3799,27 +3798,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
37993798
indexInfo->ii_ExclusionStrats=NULL;
38003799
}
38013800

3802-
/* ensure SetReindexProcessing state isn't leaked */
3803-
PG_TRY();
3804-
{
3805-
/* Suppress use of the target index while rebuilding it */
3806-
SetReindexProcessing(heapId,indexId);
3801+
/* Suppress use of the target index while rebuilding it */
3802+
SetReindexProcessing(heapId,indexId);
38073803

3808-
/* Create a new physical relation for the index */
3809-
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3810-
InvalidMultiXactId);
3804+
/* Create a new physical relation for the index */
3805+
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3806+
InvalidMultiXactId);
38113807

3812-
/* Initialize the index and rebuild */
3813-
/* Note: we do not need to re-establish pkey setting */
3814-
index_build(heapRelation,iRel,indexInfo, false, true, true);
3815-
}
3816-
PG_CATCH();
3817-
{
3818-
/* Make sure flag gets cleared on error exit */
3819-
ResetReindexProcessing();
3820-
PG_RE_THROW();
3821-
}
3822-
PG_END_TRY();
3808+
/* Initialize the index and rebuild */
3809+
/* Note: we do not need to re-establish pkey setting */
3810+
index_build(heapRelation,iRel,indexInfo, false, true, true);
3811+
3812+
/* Re-allow use of target index */
38233813
ResetReindexProcessing();
38243814

38253815
/*
@@ -3954,7 +3944,9 @@ reindex_relation(Oid relid, int flags, int options)
39543944
Relationrel;
39553945
Oidtoast_relid;
39563946
List*indexIds;
3947+
charpersistence;
39573948
boolresult;
3949+
ListCell*indexId;
39583950

39593951
/*
39603952
* Open and lock the relation. ShareLock is sufficient since we only need
@@ -3988,56 +3980,42 @@ reindex_relation(Oid relid, int flags, int options)
39883980
*/
39893981
indexIds=RelationGetIndexList(rel);
39903982

3991-
PG_TRY();
3983+
if (flags&REINDEX_REL_SUPPRESS_INDEX_USE)
39923984
{
3993-
ListCell*indexId;
3994-
charpersistence;
3995-
3996-
if (flags&REINDEX_REL_SUPPRESS_INDEX_USE)
3997-
{
3998-
/* Suppress use of all the indexes until they are rebuilt */
3999-
SetReindexPending(indexIds);
4000-
4001-
/*
4002-
* Make the new heap contents visible --- now things might be
4003-
* inconsistent!
4004-
*/
4005-
CommandCounterIncrement();
4006-
}
3985+
/* Suppress use of all the indexes until they are rebuilt */
3986+
SetReindexPending(indexIds);
40073987

40083988
/*
4009-
*Compute persistence of indexes: same as that of owning rel, unless
4010-
*caller specified otherwise.
3989+
*Make the new heap contents visible --- now things might be
3990+
*inconsistent!
40113991
*/
4012-
if (flags&REINDEX_REL_FORCE_INDEXES_UNLOGGED)
4013-
persistence=RELPERSISTENCE_UNLOGGED;
4014-
elseif (flags&REINDEX_REL_FORCE_INDEXES_PERMANENT)
4015-
persistence=RELPERSISTENCE_PERMANENT;
4016-
else
4017-
persistence=rel->rd_rel->relpersistence;
3992+
CommandCounterIncrement();
3993+
}
40183994

4019-
/* Reindex all the indexes. */
4020-
foreach(indexId,indexIds)
4021-
{
4022-
OidindexOid=lfirst_oid(indexId);
3995+
/*
3996+
* Compute persistence of indexes: same as that of owning rel, unless
3997+
* caller specified otherwise.
3998+
*/
3999+
if (flags&REINDEX_REL_FORCE_INDEXES_UNLOGGED)
4000+
persistence=RELPERSISTENCE_UNLOGGED;
4001+
elseif (flags&REINDEX_REL_FORCE_INDEXES_PERMANENT)
4002+
persistence=RELPERSISTENCE_PERMANENT;
4003+
else
4004+
persistence=rel->rd_rel->relpersistence;
40234005

4024-
reindex_index(indexOid, !(flags&REINDEX_REL_CHECK_CONSTRAINTS),
4025-
persistence,options);
4006+
/* Reindex all the indexes. */
4007+
foreach(indexId,indexIds)
4008+
{
4009+
OidindexOid=lfirst_oid(indexId);
40264010

4027-
CommandCounterIncrement();
4011+
reindex_index(indexOid, !(flags&REINDEX_REL_CHECK_CONSTRAINTS),
4012+
persistence,options);
40284013

4029-
/* Index should no longer be in the pending list */
4030-
Assert(!ReindexIsProcessingIndex(indexOid));
4031-
}
4032-
}
4033-
PG_CATCH();
4034-
{
4035-
/* Make sure list gets cleared on error exit */
4036-
ResetReindexPending();
4037-
PG_RE_THROW();
4014+
CommandCounterIncrement();
4015+
4016+
/* Index should no longer be in the pending list */
4017+
Assert(!ReindexIsProcessingIndex(indexOid));
40384018
}
4039-
PG_END_TRY();
4040-
ResetReindexPending();
40414019

40424020
/*
40434021
* Close rel, but continue to hold the lock.
@@ -4071,6 +4049,7 @@ reindex_relation(Oid relid, int flags, int options)
40714049
staticOidcurrentlyReindexedHeap=InvalidOid;
40724050
staticOidcurrentlyReindexedIndex=InvalidOid;
40734051
staticList*pendingReindexedIndexes=NIL;
4052+
staticintreindexingNestLevel=0;
40744053

40754054
/*
40764055
* ReindexIsProcessingHeap
@@ -4107,8 +4086,6 @@ ReindexIsProcessingIndex(Oid indexOid)
41074086
/*
41084087
* SetReindexProcessing
41094088
*Set flag that specified heap/index are being reindexed.
4110-
*
4111-
* NB: caller must use a PG_TRY block to ensure ResetReindexProcessing is done.
41124089
*/
41134090
staticvoid
41144091
SetReindexProcessing(OidheapOid,OidindexOid)
@@ -4121,6 +4098,8 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
41214098
currentlyReindexedIndex=indexOid;
41224099
/* Index is no longer "pending" reindex. */
41234100
RemoveReindexPending(indexOid);
4101+
/* This may have been set already, but in case it isn't, do so now. */
4102+
reindexingNestLevel=GetCurrentTransactionNestLevel();
41244103
}
41254104

41264105
/*
@@ -4130,17 +4109,16 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
41304109
staticvoid
41314110
ResetReindexProcessing(void)
41324111
{
4133-
/* This may be called in leader error path */
41344112
currentlyReindexedHeap=InvalidOid;
41354113
currentlyReindexedIndex=InvalidOid;
4114+
/* reindexingNestLevel remains set till end of (sub)transaction */
41364115
}
41374116

41384117
/*
41394118
* SetReindexPending
41404119
*Mark the given indexes as pending reindex.
41414120
*
4142-
* NB: caller must use a PG_TRY block to ensure ResetReindexPending is done.
4143-
* Also, we assume that the current memory context stays valid throughout.
4121+
* NB: we assume that the current memory context stays valid throughout.
41444122
*/
41454123
staticvoid
41464124
SetReindexPending(List*indexes)
@@ -4151,6 +4129,7 @@ SetReindexPending(List *indexes)
41514129
if (IsInParallelMode())
41524130
elog(ERROR,"cannot modify reindex state during a parallel operation");
41534131
pendingReindexedIndexes=list_copy(indexes);
4132+
reindexingNestLevel=GetCurrentTransactionNestLevel();
41544133
}
41554134

41564135
/*
@@ -4167,14 +4146,32 @@ RemoveReindexPending(Oid indexOid)
41674146
}
41684147

41694148
/*
4170-
*ResetReindexPending
4171-
*Unset reindex-pending status.
4149+
*ResetReindexState
4150+
*Clear all reindexing state during (sub)transaction abort.
41724151
*/
4173-
staticvoid
4174-
ResetReindexPending(void)
4152+
void
4153+
ResetReindexState(intnestLevel)
41754154
{
4176-
/* This may be called in leader error path */
4177-
pendingReindexedIndexes=NIL;
4155+
/*
4156+
* Because reindexing is not re-entrant, we don't need to cope with nested
4157+
* reindexing states. We just need to avoid messing up the outer-level
4158+
* state in case a subtransaction fails within a REINDEX. So checking the
4159+
* current nest level against that of the reindex operation is sufficient.
4160+
*/
4161+
if (reindexingNestLevel >=nestLevel)
4162+
{
4163+
currentlyReindexedHeap=InvalidOid;
4164+
currentlyReindexedIndex=InvalidOid;
4165+
4166+
/*
4167+
* We needn't try to release the contents of pendingReindexedIndexes;
4168+
* that list should be in a transaction-lifespan context, so it will
4169+
* go away automatically.
4170+
*/
4171+
pendingReindexedIndexes=NIL;
4172+
4173+
reindexingNestLevel=0;
4174+
}
41784175
}
41794176

41804177
/*
@@ -4227,4 +4224,7 @@ RestoreReindexState(void *reindexstate)
42274224
lappend_oid(pendingReindexedIndexes,
42284225
sistate->pendingReindexedIndexes[c]);
42294226
MemoryContextSwitchTo(oldcontext);
4227+
4228+
/* Note the worker has its own transaction nesting level */
4229+
reindexingNestLevel=GetCurrentTransactionNestLevel();
42304230
}

‎src/include/catalog/index.h

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

136136
externvoidindex_set_state_flags(OidindexId,IndexStateFlagsActionaction);
137137

138+
externOidIndexGetRelation(OidindexId,boolmissing_ok);
139+
138140
externvoidreindex_index(OidindexId,boolskip_constraint_checks,
139141
charrelpersistence,intoptions);
140142

@@ -149,8 +151,8 @@ extern bool reindex_relation(Oid relid, int flags, int options);
149151

150152
externboolReindexIsProcessingHeap(OidheapOid);
151153
externboolReindexIsProcessingIndex(OidindexOid);
152-
externOidIndexGetRelation(OidindexId,boolmissing_ok);
153154

155+
externvoidResetReindexState(intnestLevel);
154156
externSizeEstimateReindexStateSpace(void);
155157
externvoidSerializeReindexState(Sizemaxsize,char*start_address);
156158
externvoidRestoreReindexState(void*reindexstate);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp