aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/init/postinit.c11
-rw-r--r--src/backend/utils/resowner/resowner.c74
2 files changed, 70 insertions, 15 deletions
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 09e0df290dd..5ef6315d206 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -632,8 +632,19 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
* We are either a bootstrap process or a standalone backend. Either
* way, start up the XLOG machinery, and register to have it closed
* down at exit.
+ *
+ * We don't yet have an aux-process resource owner, but StartupXLOG
+ * and ShutdownXLOG will need one. Hence, create said resource owner
+ * (and register a callback to clean it up after ShutdownXLOG runs).
*/
+ CreateAuxProcessResourceOwner();
+
StartupXLOG();
+ /* Release (and warn about) any buffer pins leaked in StartupXLOG */
+ ReleaseAuxProcessResources(true);
+ /* Reset CurrentResourceOwner to nothing for the moment */
+ CurrentResourceOwner = NULL;
+
on_shmem_exit(ShutdownXLOG, 0);
}
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index bce021e1001..211833da02c 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -22,6 +22,7 @@
#include "access/hash.h"
#include "jit/jit.h"
+#include "storage/ipc.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "utils/memutils.h"
@@ -140,6 +141,7 @@ typedef struct ResourceOwnerData
ResourceOwner CurrentResourceOwner = NULL;
ResourceOwner CurTransactionResourceOwner = NULL;
ResourceOwner TopTransactionResourceOwner = NULL;
+ResourceOwner AuxProcessResourceOwner = NULL;
/*
* List of add-on callbacks for resource releasing
@@ -165,6 +167,7 @@ static void ResourceOwnerReleaseInternal(ResourceOwner owner,
ResourceReleasePhase phase,
bool isCommit,
bool isTopLevel);
+static void ReleaseAuxProcessResourcesCallback(int code, Datum arg);
static void PrintRelCacheLeakWarning(Relation rel);
static void PrintPlanCacheLeakWarning(CachedPlan *plan);
static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
@@ -823,6 +826,60 @@ UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
}
}
+/*
+ * Establish an AuxProcessResourceOwner for the current process.
+ */
+void
+CreateAuxProcessResourceOwner(void)
+{
+ Assert(AuxProcessResourceOwner == NULL);
+ Assert(CurrentResourceOwner == NULL);
+ AuxProcessResourceOwner = ResourceOwnerCreate(NULL, "AuxiliaryProcess");
+ CurrentResourceOwner = AuxProcessResourceOwner;
+
+ /*
+ * Register a shmem-exit callback for cleanup of aux-process resource
+ * owner. (This needs to run after, e.g., ShutdownXLOG.)
+ */
+ on_shmem_exit(ReleaseAuxProcessResourcesCallback, 0);
+
+}
+
+/*
+ * Convenience routine to release all resources tracked in
+ * AuxProcessResourceOwner (but that resowner is not destroyed here).
+ * Warn about leaked resources if isCommit is true.
+ */
+void
+ReleaseAuxProcessResources(bool isCommit)
+{
+ /*
+ * At this writing, the only thing that could actually get released is
+ * buffer pins; but we may as well do the full release protocol.
+ */
+ ResourceOwnerRelease(AuxProcessResourceOwner,
+ RESOURCE_RELEASE_BEFORE_LOCKS,
+ isCommit, true);
+ ResourceOwnerRelease(AuxProcessResourceOwner,
+ RESOURCE_RELEASE_LOCKS,
+ isCommit, true);
+ ResourceOwnerRelease(AuxProcessResourceOwner,
+ RESOURCE_RELEASE_AFTER_LOCKS,
+ isCommit, true);
+}
+
+/*
+ * Shmem-exit callback for the same.
+ * Warn about leaked resources if process exit code is zero (ie normal).
+ */
+static void
+ReleaseAuxProcessResourcesCallback(int code, Datum arg)
+{
+ bool isCommit = (code == 0);
+
+ ReleaseAuxProcessResources(isCommit);
+}
+
/*
* Make sure there is room for at least one more entry in a ResourceOwner's
@@ -830,15 +887,12 @@ UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
*
* This is separate from actually inserting an entry because if we run out
* of memory, it's critical to do so *before* acquiring the resource.
- *
- * We allow the case owner == NULL because the bufmgr is sometimes invoked
- * outside any transaction (for example, during WAL recovery).
*/
void
ResourceOwnerEnlargeBuffers(ResourceOwner owner)
{
- if (owner == NULL)
- return;
+ /* We used to allow pinning buffers without a resowner, but no more */
+ Assert(owner != NULL);
ResourceArrayEnlarge(&(owner->bufferarr));
}
@@ -846,29 +900,19 @@ ResourceOwnerEnlargeBuffers(ResourceOwner owner)
* Remember that a buffer pin is owned by a ResourceOwner
*
* Caller must have previously done ResourceOwnerEnlargeBuffers()
- *
- * We allow the case owner == NULL because the bufmgr is sometimes invoked
- * outside any transaction (for example, during WAL recovery).
*/
void
ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
{
- if (owner == NULL)
- return;
ResourceArrayAdd(&(owner->bufferarr), BufferGetDatum(buffer));
}
/*
* Forget that a buffer pin is owned by a ResourceOwner
- *
- * We allow the case owner == NULL because the bufmgr is sometimes invoked
- * outside any transaction (for example, during WAL recovery).
*/
void
ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
{
- if (owner == NULL)
- return;
if (!ResourceArrayRemove(&(owner->bufferarr), BufferGetDatum(buffer)))
elog(ERROR, "buffer %d is not owned by resource owner %s",
buffer, owner->name);