Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4d2a844

Browse files
committed
Allow callback functions to deregister themselves during a call.
Fetch the next-item pointer before the call not after, so that we aren't dereferencing a dangling pointer if the callback deregistered itself during the call. The risky coding pattern appears in CallXactCallbacks, CallSubXactCallbacks, and ResourceOwnerReleaseInternal. (There are some other places that might be at hazard if they offered deregistration functionality, but they don't.) I (tgl) considered back-patching this, but desisted because it wouldn't be very safe for extensions to rely on this working in pre-v16 branches. Hao Wu Discussion: https://postgr.es/m/CAH+9SWXTiERkmhRke+QCcc+jRH8d5fFHTxh8ZK0-Yn4BSpyaAg@mail.gmail.com
1 parent d84a7b2 commit 4d2a844

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/backend/access/transam/xact.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -3656,9 +3656,14 @@ static void
36563656
CallXactCallbacks(XactEvent event)
36573657
{
36583658
XactCallbackItem *item;
3659+
XactCallbackItem *next;
36593660

3660-
for (item = Xact_callbacks; item; item = item->next)
3661+
for (item = Xact_callbacks; item; item = next)
3662+
{
3663+
/* allow callbacks to unregister themselves when called */
3664+
next = item->next;
36613665
item->callback(event, item->arg);
3666+
}
36623667
}
36633668

36643669

@@ -3713,9 +3718,14 @@ CallSubXactCallbacks(SubXactEvent event,
37133718
SubTransactionId parentSubid)
37143719
{
37153720
SubXactCallbackItem *item;
3721+
SubXactCallbackItem *next;
37163722

3717-
for (item = SubXact_callbacks; item; item = item->next)
3723+
for (item = SubXact_callbacks; item; item = next)
3724+
{
3725+
/* allow callbacks to unregister themselves when called */
3726+
next = item->next;
37183727
item->callback(event, mySubid, parentSubid, item->arg);
3728+
}
37193729
}
37203730

37213731

src/backend/utils/resowner/resowner.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
501501
ResourceOwner child;
502502
ResourceOwner save;
503503
ResourceReleaseCallbackItem *item;
504+
ResourceReleaseCallbackItem *next;
504505
Datum foundres;
505506

506507
/* Recurse to handle descendants */
@@ -701,8 +702,12 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
701702
}
702703

703704
/* Let add-on modules get a chance too */
704-
for (item = ResourceRelease_callbacks; item; item = item->next)
705+
for (item = ResourceRelease_callbacks; item; item = next)
706+
{
707+
/* allow callbacks to unregister themselves when called */
708+
next = item->next;
705709
item->callback(phase, isCommit, isTopLevel, item->arg);
710+
}
706711

707712
CurrentResourceOwner = save;
708713
}

0 commit comments

Comments
 (0)