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

Commit21786db

Browse files
committed
Fix cache flush hazard in event trigger cache.
Bug spotted by Jeff Davis using -DCLOBBER_CACHE_ALWAYS.
1 parent2751740 commit21786db

File tree

1 file changed

+39
-16
lines changed

1 file changed

+39
-16
lines changed

‎src/backend/utils/cache/evtcache.c

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
#include"utils/snapmgr.h"
3030
#include"utils/syscache.h"
3131

32+
typedefenum
33+
{
34+
ETCS_NEEDS_REBUILD,
35+
ETCS_REBUILD_STARTED,
36+
ETCS_VALID
37+
}EventTriggerCacheStateType;
38+
3239
typedefstruct
3340
{
3441
EventTriggerEventevent;
@@ -37,6 +44,7 @@ typedef struct
3744

3845
staticHTAB*EventTriggerCache;
3946
staticMemoryContextEventTriggerCacheContext;
47+
staticEventTriggerCacheStateTypeEventTriggerCacheState=ETCS_NEEDS_REBUILD;
4048

4149
staticvoidBuildEventTriggerCache(void);
4250
staticvoidInvalidateEventCacheCallback(Datumarg,
@@ -55,7 +63,7 @@ EventCacheLookup(EventTriggerEvent event)
5563
{
5664
EventTriggerCacheEntry*entry;
5765

58-
if (EventTriggerCache==NULL)
66+
if (EventTriggerCacheState!=ETCS_VALID)
5967
BuildEventTriggerCache();
6068
entry=hash_search(EventTriggerCache,&event,HASH_FIND,NULL);
6169
returnentry!=NULL ?entry->triggerlist :NULL;
@@ -77,12 +85,9 @@ BuildEventTriggerCache(void)
7785
if (EventTriggerCacheContext!=NULL)
7886
{
7987
/*
80-
* The cache has been previously built, and subsequently invalidated,
81-
* and now we're trying to rebuild it. Normally, there won't be
82-
* anything in the context at this point, because the invalidation
83-
* will have already reset it. But if the previous attempt to rebuild
84-
* the cache failed, then there might be some junk lying around
85-
* that we want to reclaim.
88+
* Free up any memory already allocated in EventTriggerCacheContext.
89+
* This can happen either because a previous rebuild failed, or
90+
* because an invalidation happened before the rebuild was complete.
8691
*/
8792
MemoryContextResetAndDeleteChildren(EventTriggerCacheContext);
8893
}
@@ -109,12 +114,10 @@ BuildEventTriggerCache(void)
109114
/* Switch to correct memory context. */
110115
oldcontext=MemoryContextSwitchTo(EventTriggerCacheContext);
111116

112-
/*
113-
* Create a new hash table, but don't assign it to the global variable
114-
* until it accurately represents the state of the catalogs, so that
115-
* if we fail midway through this we won't end up with incorrect cache
116-
* contents.
117-
*/
117+
/* Prevent the memory context from being nuked while we're rebuilding. */
118+
EventTriggerCacheState=ETCS_REBUILD_STARTED;
119+
120+
/* Create new hash table. */
118121
MemSet(&ctl,0,sizeof(ctl));
119122
ctl.keysize=sizeof(EventTriggerEvent);
120123
ctl.entrysize=sizeof(EventTriggerCacheEntry);
@@ -195,8 +198,17 @@ BuildEventTriggerCache(void)
195198
/* Restore previous memory context. */
196199
MemoryContextSwitchTo(oldcontext);
197200

198-
/*Cache is now valid. */
201+
/*Install new cache. */
199202
EventTriggerCache=cache;
203+
204+
/*
205+
* If the cache has been invalidated since we entered this routine, we
206+
* still use and return the cache we just finished constructing, to avoid
207+
* infinite loops, but we leave the cache marked stale so that we'll
208+
* rebuild it again on next access. Otherwise, we mark the cache valid.
209+
*/
210+
if (EventTriggerCacheState==ETCS_REBUILD_STARTED)
211+
EventTriggerCacheState=ETCS_VALID;
200212
}
201213

202214
/*
@@ -238,6 +250,17 @@ DecodeTextArrayToCString(Datum array, char ***cstringp)
238250
staticvoid
239251
InvalidateEventCacheCallback(Datumarg,intcacheid,uint32hashvalue)
240252
{
241-
MemoryContextResetAndDeleteChildren(EventTriggerCacheContext);
242-
EventTriggerCache=NULL;
253+
/*
254+
* If the cache isn't valid, then there might be a rebuild in progress,
255+
* so we can't immediately blow it away. But it's advantageous to do
256+
* this when possible, so as to immediately free memory.
257+
*/
258+
if (EventTriggerCacheState==ETCS_VALID)
259+
{
260+
MemoryContextResetAndDeleteChildren(EventTriggerCacheContext);
261+
EventTriggerCache=NULL;
262+
}
263+
264+
/* Mark cache for rebuild. */
265+
EventTriggerCacheState=ETCS_NEEDS_REBUILD;
243266
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp