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

Commit cac32a9

Browse files
author
Nikita Glukhov
committed
Fix memory leaks in jsonb_toaster methods using cached temporary context
1 parent cdceadf commit cac32a9

File tree

1 file changed

+116
-15
lines changed

1 file changed

+116
-15
lines changed

contrib/jsonb_toaster/jsonb_toaster.c

+116-15
Original file line numberDiff line numberDiff line change
@@ -3652,6 +3652,103 @@ jsonb_toaster_default_toast(Relation rel, Oid toasterid, char cmethod,
36523652
NULL, options, NULL, NULL, false);
36533653
}
36543654

3655+
/* #define JSONB_TOASTER_TRACK_NESTING 1 FIXME this needs PG_TRY/PG_CATCH */
3656+
3657+
#ifdef JSONB_TOASTER_TRACK_NESTING
3658+
static int jsonb_toaster_nesting_level;
3659+
#endif
3660+
3661+
static MemoryContext jsonb_toaster_parent_cxt;
3662+
static MemoryContext jsonb_toaster_temp_cxt;
3663+
3664+
static void
3665+
jsonb_toaster_temp_context_reset_callback(void *arg)
3666+
{
3667+
if (jsonb_toaster_temp_cxt == arg)
3668+
jsonb_toaster_temp_cxt = NULL;
3669+
}
3670+
3671+
static void
3672+
jsonb_toaster_register_temp_context_callback(MemoryContext temp_cxt)
3673+
{
3674+
MemoryContextCallback *cb;
3675+
3676+
cb = MemoryContextAlloc(temp_cxt, sizeof(*cb));
3677+
cb->func = jsonb_toaster_temp_context_reset_callback;
3678+
cb->arg = temp_cxt;
3679+
3680+
MemoryContextRegisterResetCallback(temp_cxt, cb);
3681+
}
3682+
3683+
static void
3684+
jsonb_toaster_init_temp_context()
3685+
{
3686+
#ifdef JSONB_TOASTER_TRACK_NESTING
3687+
if (jsonb_toaster_nesting_level++ > 0)
3688+
return;
3689+
#endif
3690+
3691+
if (!jsonb_toaster_temp_cxt ||
3692+
jsonb_toaster_parent_cxt != CurrentMemoryContext)
3693+
{
3694+
MemoryContext temp_cxt;
3695+
3696+
if (jsonb_toaster_temp_cxt)
3697+
{
3698+
temp_cxt = jsonb_toaster_temp_cxt;
3699+
jsonb_toaster_temp_cxt = NULL;
3700+
MemoryContextDelete(temp_cxt);
3701+
}
3702+
3703+
temp_cxt = AllocSetContextCreate(CurrentMemoryContext,
3704+
"jsonb_toaster temp context",
3705+
ALLOCSET_DEFAULT_SIZES);
3706+
3707+
jsonb_toaster_register_temp_context_callback(temp_cxt);
3708+
3709+
jsonb_toaster_parent_cxt = CurrentMemoryContext;
3710+
jsonb_toaster_temp_cxt = temp_cxt;
3711+
}
3712+
3713+
MemoryContextSwitchTo(jsonb_toaster_temp_cxt);
3714+
3715+
jsonbInitIterators();
3716+
}
3717+
3718+
static Datum
3719+
jsonb_toaster_free_temp_context(Datum result)
3720+
{
3721+
MemoryContext temp_cxt;
3722+
3723+
#ifdef JSONB_TOASTER_TRACK_NESTING
3724+
if (jsonb_toaster_nesting_level-- > 1)
3725+
return;
3726+
#endif
3727+
3728+
Assert(CurrentMemoryContext == jsonb_toaster_temp_cxt);
3729+
3730+
jsonbFreeIterators();
3731+
3732+
MemoryContextSwitchTo(jsonb_toaster_parent_cxt);
3733+
3734+
/* Copy result from from temporary context, if any */
3735+
if (result)
3736+
{
3737+
int size = VARSIZE_ANY(result);
3738+
3739+
result = PointerGetDatum(memcpy(palloc(size), DatumGetPointer(result), size));
3740+
}
3741+
3742+
temp_cxt = jsonb_toaster_temp_cxt;
3743+
MemoryContextReset(temp_cxt);
3744+
3745+
/* Restore jsonb_toaster_temp_cxt after reset callback execution */
3746+
jsonb_toaster_temp_cxt = temp_cxt;
3747+
jsonb_toaster_register_temp_context_callback(temp_cxt);
3748+
3749+
return result;
3750+
}
3751+
36553752
static Datum
36563753
jsonb_toaster_toast(Relation rel, Oid toasterid,
36573754
Datum new_val, Datum old_val,
@@ -3661,7 +3758,7 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
36613758
Datum res;
36623759
char cmethod = TOAST_PGLZ_COMPRESSION;
36633760

3664-
jsonbInitIterators();
3761+
jsonb_toaster_init_temp_context();
36653762

36663763
new_js = DatumGetJsonbPC(new_val, NULL /* FIXME alloca */, false);
36673764

@@ -3674,9 +3771,13 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
36743771
new_val, new_js,
36753772
max_inline_size, options);
36763773

3677-
res = res == (Datum) 0 ? new_val : res;
3678-
3679-
jsonbFreeIterators();
3774+
if (res == (Datum) 0 || res == new_val)
3775+
{
3776+
res = new_val;
3777+
jsonb_toaster_free_temp_context(0);
3778+
}
3779+
else
3780+
res = jsonb_toaster_free_temp_context(res);
36803781

36813782
return res;
36823783
}
@@ -3691,13 +3792,13 @@ jsonb_toaster_update_toast(Relation rel, Oid toasterid,
36913792
Datum res;
36923793
char cmethod = TOAST_PGLZ_COMPRESSION;
36933794

3694-
jsonbInitIterators();
3795+
jsonb_toaster_init_temp_context();
36953796

36963797
new_js = DatumGetJsonbPC(new_val, NULL, false);
36973798
old_js = DatumGetJsonbPC(old_val, NULL, false);
36983799
res = jsonb_toaster_cmp(rel, toasterid, JsonRoot(new_js), JsonRoot(old_js), cmethod);
36993800

3700-
jsonbFreeIterators();
3801+
res = jsonb_toaster_free_temp_context(res);
37013802

37023803
return res;
37033804
}
@@ -3710,12 +3811,12 @@ jsonb_toaster_copy_toast(Relation rel, Oid toasterid,
37103811
Datum res;
37113812
char cmethod = TOAST_PGLZ_COMPRESSION;
37123813

3713-
jsonbInitIterators();
3814+
jsonb_toaster_init_temp_context();
37143815

37153816
new_js = DatumGetJsonbPC(new_val, NULL, false);
37163817
res = jsonb_toaster_copy(rel, toasterid, JsonRoot(new_js), cmethod, true);
37173818

3718-
jsonbFreeIterators();
3819+
res = jsonb_toaster_free_temp_context(res);
37193820

37203821
return res;
37213822
}
@@ -3725,12 +3826,12 @@ jsonb_toaster_delete_toast(Datum val, bool is_speculative)
37253826
{
37263827
Json *js;
37273828

3728-
jsonbInitIterators();
3829+
jsonb_toaster_init_temp_context();
37293830

37303831
js = DatumGetJsonbPC(val, NULL, false);
37313832
jsonb_toaster_delete_recursive(NULL /* XXX rel */, JsonRoot(js), false, is_speculative);
37323833

3733-
jsonbFreeIterators();
3834+
jsonb_toaster_free_temp_context(0);
37343835
}
37353836

37363837
static Datum
@@ -3742,10 +3843,11 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37423843
JsonValue bin;
37433844
void *detoasted;
37443845
int len;
3846+
MemoryContext mcxt = CurrentMemoryContext;
37453847

37463848
Assert(VARATT_IS_CUSTOM(toastptr));
37473849

3748-
jsonbInitIterators();
3850+
jsonb_toaster_init_temp_context();
37493851

37503852
//js = DatumGetJson(toastptr, &jsonxContainerOps, &jsbuf);
37513853
js = JsonExpand(NULL /* FIXME &jsbuf */, toastptr, false, &jsonxContainerOps);
@@ -3755,10 +3857,8 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37553857
detoasted = JsonEncode(&bin, JsonbEncode, NULL);
37563858
len = VARSIZE_ANY_EXHDR(detoasted);
37573859

3758-
jsonbFreeIterators();
3759-
37603860
if (sliceoffset == 0 && (slicelength < 0 || slicelength >= len))
3761-
return PointerGetDatum(detoasted);
3861+
return jsonb_toaster_free_temp_context(PointerGetDatum(detoasted));
37623862

37633863
if (sliceoffset < 0)
37643864
sliceoffset = 0;
@@ -3768,11 +3868,12 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37683868
if (slicelength < 0 || sliceoffset + slicelength > len)
37693869
slicelength = len - sliceoffset;
37703870

3771-
result = palloc(VARHDRSZ + slicelength);
3871+
result = MemoryContextAlloc(mcxt, VARHDRSZ + slicelength);
37723872
SET_VARSIZE(result, VARHDRSZ + slicelength);
37733873
memcpy(VARDATA(result), (char *) VARDATA_ANY(detoasted) + sliceoffset, slicelength);
37743874

37753875
pfree(detoasted);
3876+
jsonb_toaster_free_temp_context(0);
37763877

37773878
return PointerGetDatum(result);
37783879
}

0 commit comments

Comments
 (0)