Skip to content

Commit 4863ed8

Browse files
committed
Fix intermittent crash in DROP INDEX CONCURRENTLY.
When deleteOneObject closes and reopens the pg_depend relation, we must see to it that the relcache pointer held by the calling function (typically performMultipleDeletions) is updated. Usually the relcache entry is retained so that the pointer value doesn't change, which is why the problem had escaped notice ... but after a cache flush event there's no guarantee that the same memory will be reassigned. To fix, change the recursive functions' APIs so that we pass around a "Relation *" not just "Relation". Per investigation of occasional buildfarm failures. This is trivial to reproduce with -DCLOBBER_CACHE_ALWAYS, which points up the sad lack of any buildfarm member running that way on a regular basis.
1 parent 161021d commit 4863ed8

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

src/backend/catalog/dependency.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,13 @@ static void findDependentObjects(const ObjectAddress *object,
167167
ObjectAddressStack *stack,
168168
ObjectAddresses *targetObjects,
169169
const ObjectAddresses *pendingObjects,
170-
Relation depRel);
170+
Relation *depRel);
171171
static void reportDependentObjects(const ObjectAddresses *targetObjects,
172172
DropBehavior behavior,
173173
int msglevel,
174174
const ObjectAddress *origObject);
175175
static void deleteOneObject(const ObjectAddress *object,
176-
Relation depRel, int32 flags);
176+
Relation *depRel, int32 flags);
177177
static void doDeletion(const ObjectAddress *object, int flags);
178178
static void AcquireDeletionLock(const ObjectAddress *object, int flags);
179179
static void ReleaseDeletionLock(const ObjectAddress *object);
@@ -246,7 +246,7 @@ performDeletion(const ObjectAddress *object,
246246
NULL, /* empty stack */
247247
targetObjects,
248248
NULL, /* no pendingObjects */
249-
depRel);
249+
&depRel);
250250

251251
/*
252252
* Check if deletion is allowed, and report about cascaded deletes.
@@ -263,7 +263,7 @@ performDeletion(const ObjectAddress *object,
263263
{
264264
ObjectAddress *thisobj = targetObjects->refs + i;
265265

266-
deleteOneObject(thisobj, depRel, flags);
266+
deleteOneObject(thisobj, &depRel, flags);
267267
}
268268

269269
/* And clean up */
@@ -324,7 +324,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
324324
NULL, /* empty stack */
325325
targetObjects,
326326
objects,
327-
depRel);
327+
&depRel);
328328
}
329329

330330
/*
@@ -345,7 +345,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
345345
{
346346
ObjectAddress *thisobj = targetObjects->refs + i;
347347

348-
deleteOneObject(thisobj, depRel, flags);
348+
deleteOneObject(thisobj, &depRel, flags);
349349
}
350350

351351
/* And clean up */
@@ -394,7 +394,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
394394
NULL, /* empty stack */
395395
targetObjects,
396396
NULL, /* no pendingObjects */
397-
depRel);
397+
&depRel);
398398

399399
/*
400400
* Check if deletion is allowed, and report about cascaded deletes.
@@ -423,7 +423,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
423423
* action. If, in the future, this function is used for other
424424
* purposes, we might need to revisit this.
425425
*/
426-
deleteOneObject(thisobj, depRel, PERFORM_DELETION_INTERNAL);
426+
deleteOneObject(thisobj, &depRel, PERFORM_DELETION_INTERNAL);
427427
}
428428

429429
/* And clean up */
@@ -458,15 +458,15 @@ deleteWhatDependsOn(const ObjectAddress *object,
458458
* targetObjects: list of objects that are scheduled to be deleted
459459
* pendingObjects: list of other objects slated for destruction, but
460460
* not necessarily in targetObjects yet (can be NULL if none)
461-
* depRel: already opened pg_depend relation
461+
* *depRel: already opened pg_depend relation
462462
*/
463463
static void
464464
findDependentObjects(const ObjectAddress *object,
465465
int flags,
466466
ObjectAddressStack *stack,
467467
ObjectAddresses *targetObjects,
468468
const ObjectAddresses *pendingObjects,
469-
Relation depRel)
469+
Relation *depRel)
470470
{
471471
ScanKeyData key[3];
472472
int nkeys;
@@ -536,7 +536,7 @@ findDependentObjects(const ObjectAddress *object,
536536
else
537537
nkeys = 2;
538538

539-
scan = systable_beginscan(depRel, DependDependerIndexId, true,
539+
scan = systable_beginscan(*depRel, DependDependerIndexId, true,
540540
SnapshotNow, nkeys, key);
541541

542542
while (HeapTupleIsValid(tup = systable_getnext(scan)))
@@ -711,7 +711,7 @@ findDependentObjects(const ObjectAddress *object,
711711
else
712712
nkeys = 2;
713713

714-
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
714+
scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
715715
SnapshotNow, nkeys, key);
716716

717717
while (HeapTupleIsValid(tup = systable_getnext(scan)))
@@ -982,10 +982,10 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
982982
/*
983983
* deleteOneObject: delete a single object for performDeletion.
984984
*
985-
* depRel is the already-open pg_depend relation.
985+
* *depRel is the already-open pg_depend relation.
986986
*/
987987
static void
988-
deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
988+
deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
989989
{
990990
ScanKeyData key[3];
991991
int nkeys;
@@ -1008,7 +1008,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
10081008
* relation open across doDeletion().
10091009
*/
10101010
if (flags & PERFORM_DELETION_CONCURRENTLY)
1011-
heap_close(depRel, RowExclusiveLock);
1011+
heap_close(*depRel, RowExclusiveLock);
10121012

10131013
/*
10141014
* Delete the object itself, in an object-type-dependent way.
@@ -1025,7 +1025,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
10251025
* Reopen depRel if we closed it above
10261026
*/
10271027
if (flags & PERFORM_DELETION_CONCURRENTLY)
1028-
depRel = heap_open(DependRelationId, RowExclusiveLock);
1028+
*depRel = heap_open(DependRelationId, RowExclusiveLock);
10291029

10301030
/*
10311031
* Now remove any pg_depend records that link from this object to others.
@@ -1053,12 +1053,12 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
10531053
else
10541054
nkeys = 2;
10551055

1056-
scan = systable_beginscan(depRel, DependDependerIndexId, true,
1056+
scan = systable_beginscan(*depRel, DependDependerIndexId, true,
10571057
SnapshotNow, nkeys, key);
10581058

10591059
while (HeapTupleIsValid(tup = systable_getnext(scan)))
10601060
{
1061-
simple_heap_delete(depRel, &tup->t_self);
1061+
simple_heap_delete(*depRel, &tup->t_self);
10621062
}
10631063

10641064
systable_endscan(scan);

0 commit comments

Comments
 (0)