Skip to content

Commit

Permalink
Fix double-loading of extension
Browse files Browse the repository at this point in the history
Previously, there was a case involving cache invalidation when
the extension could be preloaded. Namely the following happened:

1) extension_check (outer) was called and found loaded = true.
2) While the extension_check was checking the state of the extension
   a cache invalidation callback happened.
3) The cache invalidation callback called extension_check (inner).
4) The inner extension_check loads the extension and sets
   loaded = true.
5) The outer extension_check also loads the extension after the
   cache invalidation callback returns. This happens because it
   never re-checks the value of loaded.

This commit adds another check of loaded just before it is changed
to prevent this situation.
  • Loading branch information
cevian authored and dschniepp committed Apr 26, 2018
1 parent 06f7663 commit 8c24f52
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,22 @@ do_load()
StrNCpy(soversion, version, MAX_VERSION_LEN);
snprintf(soname, MAX_SO_NAME_LEN, "%s-%s", EXTENSION_NAME, version);

/*
* An inval_relcache callback can be called after previous checks of
* loaded had found it to be false. But the inval_relcache callback may
* load the extension setting it to true. Thus it needs to be rechecked
* here again by the outer call after inval_relcache completes. This is
* double-check locking, in effect.
*/
if (loaded)
return;

/*
* Set to true whether or not the load succeeds to prevent reloading if
* failure happened after partial load.
*/
loaded = true;

/*
* we need to capture the loaded extension's post analyze hook, giving it
* a NULL as previous
Expand All @@ -283,13 +299,9 @@ do_load()
PG_TRY();
{
load_file(soname, false);
loaded = true;
}
PG_CATCH();
{
/* Assume the extension was loaded to prevent re-loading another .so */
loaded = true;

extension_post_parse_analyze_hook = post_parse_analyze_hook;
post_parse_analyze_hook = old_hook;
PG_RE_THROW();
Expand Down

0 comments on commit 8c24f52

Please sign in to comment.