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

Commit4ddd8f5

Browse files
committed
Fix memory leak in TRUNCATE decoding
When decoding a TRUNCATE record, the relids array was being allocated inthe main ReorderBuffer memory context, but not released with the changeresulting in a memory leak.The array was also ignored when serializing/deserializing the change,assuming all the information is stored in the change itself. So whenspilling the change to disk, we've only we have serialized only thepointer to the relids array. Thanks to never releasing the array,the pointer however remained valid even after loading the change backto memory, preventing an actual crash.This fixes both the memory leak and (de)serialization. The relids arrayis still allocated in the main ReorderBuffer memory context (none of theexisting ones seems like a good match, and adding an extra context seemslike an overkill). The allocation is wrapped in a new ReorderBuffer APIfunctions, to keep the details within reorderbuffer.c, just like theother ReorderBufferGet methods do.Author: Tomas VondraDiscussion:https://www.postgresql.org/message-id/flat/66175a41-9342-2845-652f-1bd4c3ee50aa%402ndquadrant.comBackpatch: 11, where decoding of TRUNCATE was introduced
1 parentcaa0c6c commit4ddd8f5

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

‎src/backend/replication/logical/decode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,8 @@ DecodeTruncate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
859859
if (xlrec->flags&XLH_TRUNCATE_RESTART_SEQS)
860860
change->data.truncate.restart_seqs= true;
861861
change->data.truncate.nrelids=xlrec->nrelids;
862-
change->data.truncate.relids=palloc(xlrec->nrelids*sizeof(Oid));
862+
change->data.truncate.relids=ReorderBufferGetRelids(ctx->reorder,
863+
xlrec->nrelids);
863864
memcpy(change->data.truncate.relids,xlrec->relids,
864865
xlrec->nrelids*sizeof(Oid));
865866
ReorderBufferQueueChange(ctx->reorder,XLogRecGetXid(r),

‎src/backend/replication/logical/reorderbuffer.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,16 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change)
409409
}
410410
break;
411411
/* no data in addition to the struct itself */
412+
caseREORDER_BUFFER_CHANGE_TRUNCATE:
413+
if (change->data.truncate.relids!=NULL)
414+
{
415+
ReorderBufferReturnRelids(rb,change->data.truncate.relids);
416+
change->data.truncate.relids=NULL;
417+
}
418+
break;
412419
caseREORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM:
413420
caseREORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
414421
caseREORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
415-
caseREORDER_BUFFER_CHANGE_TRUNCATE:
416422
break;
417423
}
418424

@@ -450,6 +456,37 @@ ReorderBufferReturnTupleBuf(ReorderBuffer *rb, ReorderBufferTupleBuf *tuple)
450456
pfree(tuple);
451457
}
452458

459+
/*
460+
* Get an array for relids of truncated relations.
461+
*
462+
* We use the global memory context (for the whole reorder buffer), because
463+
* none of the existing ones seems like a good match (some are SLAB, so we
464+
* can't use those, and tup_context is meant for tuple data, not relids). We
465+
* could add yet another context, but it seems like an overkill - TRUNCATE is
466+
* not particularly common operation, so it does not seem worth it.
467+
*/
468+
Oid*
469+
ReorderBufferGetRelids(ReorderBuffer*rb,intnrelids)
470+
{
471+
Oid*relids;
472+
Sizealloc_len;
473+
474+
alloc_len=sizeof(Oid)*nrelids;
475+
476+
relids= (Oid*)MemoryContextAlloc(rb->context,alloc_len);
477+
478+
returnrelids;
479+
}
480+
481+
/*
482+
* Free an array of relids.
483+
*/
484+
void
485+
ReorderBufferReturnRelids(ReorderBuffer*rb,Oid*relids)
486+
{
487+
pfree(relids);
488+
}
489+
453490
/*
454491
* Return the ReorderBufferTXN from the given buffer, specified by Xid.
455492
* If create is true, and a transaction doesn't already exist, create it
@@ -2412,6 +2449,26 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
24122449
break;
24132450
}
24142451
caseREORDER_BUFFER_CHANGE_TRUNCATE:
2452+
{
2453+
Sizesize;
2454+
char*data;
2455+
2456+
/* account for the OIDs of truncated relations */
2457+
size=sizeof(Oid)*change->data.truncate.nrelids;
2458+
sz+=size;
2459+
2460+
/* make sure we have enough space */
2461+
ReorderBufferSerializeReserve(rb,sz);
2462+
2463+
data= ((char*)rb->outbuf)+sizeof(ReorderBufferDiskChange);
2464+
/* might have been reallocated above */
2465+
ondisk= (ReorderBufferDiskChange*)rb->outbuf;
2466+
2467+
memcpy(data,change->data.truncate.relids,size);
2468+
data+=size;
2469+
2470+
break;
2471+
}
24152472
caseREORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM:
24162473
caseREORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
24172474
caseREORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
@@ -2695,6 +2752,16 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
26952752
}
26962753
/* the base struct contains all the data, easy peasy */
26972754
caseREORDER_BUFFER_CHANGE_TRUNCATE:
2755+
{
2756+
Oid*relids;
2757+
2758+
relids=ReorderBufferGetRelids(rb,
2759+
change->data.truncate.nrelids);
2760+
memcpy(relids,data,change->data.truncate.nrelids*sizeof(Oid));
2761+
change->data.truncate.relids=relids;
2762+
2763+
break;
2764+
}
26982765
caseREORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM:
26992766
caseREORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
27002767
caseREORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:

‎src/include/replication/reorderbuffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ voidReorderBufferReturnTupleBuf(ReorderBuffer *, ReorderBufferTupleBuf *tuple)
402402
ReorderBufferChange*ReorderBufferGetChange(ReorderBuffer*);
403403
voidReorderBufferReturnChange(ReorderBuffer*,ReorderBufferChange*);
404404

405+
Oid*ReorderBufferGetRelids(ReorderBuffer*,intnrelids);
406+
voidReorderBufferReturnRelids(ReorderBuffer*,Oid*relids);
407+
405408
voidReorderBufferQueueChange(ReorderBuffer*,TransactionId,XLogRecPtrlsn,ReorderBufferChange*);
406409
voidReorderBufferQueueMessage(ReorderBuffer*,TransactionId,Snapshotsnapshot,XLogRecPtrlsn,
407410
booltransactional,constchar*prefix,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp