Since commit
fb56418d66 the snapshots are computed in thread-local
storage, but we haven't been freeing the memory (on thread exit).
As the memory is allocated in the global (TopMostMemoryContext),
this presented a memory leak of 64kB on each GTM connection.
One way to fix this would be to track when the thread-local storage
is used in GTM_GetTransactionSnapshot(), and allocate the memory
in TopMemoryContext (which is per-thread and released on exit).
But there's a simpler way - allocate the thread-specific storage as
part of GTM_ThreadInfo, and just redirect sn_xip from the snapshot.
This way we don't have to worry about palloc/pfree at all, and we
mostly assume that every connection will need to compute at least
one snapshot anyway.
Reported by Rob Canavan <
[email protected]>, investigation and fix
by me. For more discussion see
<CAFTg0q6VC_11+c=Q=gsAcDsBrDjvuGKjzNwH4Lr8vERRDn4Ycw@mail.gmail.com>
Backpatch to Postgres-XL 9.5.
Assert(snapshot != NULL);
+ /*
+ * This can only happen when using a snapshot from GTMTransactions, as the
+ * thread-specific sn_xip array is allocated statically as part of GTM_ThreadInfo.
+ */
if (snapshot->sn_xip == NULL)
{
/*
8 * 1024,
false);
+ /*
+ * Set the sn_xip pointer to the statically-allocated array (see GTM_ThreadInfo).
+ */
+ thrinfo->thr_snapshot.sn_xip = thrinfo->thr_xip;
+
thrinfo->thr_startroutine = startroutine;
/*
GTM_RWLock thr_lock;
gtm_List *thr_cached_txninfo;
GTM_SnapshotData thr_snapshot;
+
+ /*
+ * Statically allocated XID array for the snapshot. Every thread will need
+ * a snapshot anyway, and this way we don't have to worry about allocation
+ * and freeing of the memory at thread exit.
+ */
+ GlobalTransactionId thr_xip[GTM_MAX_GLOBAL_TRANSACTIONS];
} GTM_ThreadInfo;
typedef struct GTM_Threads