Skip to content

Commit f5e1fb7

Browse files
author
Commitfest Bot
committed
[CF 5748] v3 - Improve Valgrind support and remove some memory leaks
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5748 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/[email protected] Author(s): Tom Lane
2 parents a2c6c4e + d8480a7 commit f5e1fb7

File tree

31 files changed

+546
-125
lines changed

31 files changed

+546
-125
lines changed

src/backend/access/transam/xlog.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ static void InitControlFile(uint64 sysidentifier, uint32 data_checksum_version);
703703
static void WriteControlFile(void);
704704
static void ReadControlFile(void);
705705
static void UpdateControlFile(void);
706-
static char *str_time(pg_time_t tnow);
706+
static char *str_time(pg_time_t tnow, char *buf, size_t bufsize);
707707

708708
static int get_sync_bit(int method);
709709

@@ -5371,11 +5371,9 @@ BootStrapXLOG(uint32 data_checksum_version)
53715371
}
53725372

53735373
static char *
5374-
str_time(pg_time_t tnow)
5374+
str_time(pg_time_t tnow, char *buf, size_t bufsize)
53755375
{
5376-
char *buf = palloc(128);
5377-
5378-
pg_strftime(buf, 128,
5376+
pg_strftime(buf, bufsize,
53795377
"%Y-%m-%d %H:%M:%S %Z",
53805378
pg_localtime(&tnow, log_timezone));
53815379

@@ -5618,6 +5616,7 @@ StartupXLOG(void)
56185616
XLogRecPtr missingContrecPtr;
56195617
TransactionId oldestActiveXID;
56205618
bool promoted = false;
5619+
char timebuf[128];
56215620

56225621
/*
56235622
* We should have an aux process resource owner to use, and we should not
@@ -5646,41 +5645,47 @@ StartupXLOG(void)
56465645
*/
56475646
ereport(IsPostmasterEnvironment ? LOG : NOTICE,
56485647
(errmsg("database system was shut down at %s",
5649-
str_time(ControlFile->time))));
5648+
str_time(ControlFile->time,
5649+
timebuf, sizeof(timebuf)))));
56505650
break;
56515651

56525652
case DB_SHUTDOWNED_IN_RECOVERY:
56535653
ereport(LOG,
56545654
(errmsg("database system was shut down in recovery at %s",
5655-
str_time(ControlFile->time))));
5655+
str_time(ControlFile->time,
5656+
timebuf, sizeof(timebuf)))));
56565657
break;
56575658

56585659
case DB_SHUTDOWNING:
56595660
ereport(LOG,
56605661
(errmsg("database system shutdown was interrupted; last known up at %s",
5661-
str_time(ControlFile->time))));
5662+
str_time(ControlFile->time,
5663+
timebuf, sizeof(timebuf)))));
56625664
break;
56635665

56645666
case DB_IN_CRASH_RECOVERY:
56655667
ereport(LOG,
56665668
(errmsg("database system was interrupted while in recovery at %s",
5667-
str_time(ControlFile->time)),
5669+
str_time(ControlFile->time,
5670+
timebuf, sizeof(timebuf))),
56685671
errhint("This probably means that some data is corrupted and"
56695672
" you will have to use the last backup for recovery.")));
56705673
break;
56715674

56725675
case DB_IN_ARCHIVE_RECOVERY:
56735676
ereport(LOG,
56745677
(errmsg("database system was interrupted while in recovery at log time %s",
5675-
str_time(ControlFile->checkPointCopy.time)),
5678+
str_time(ControlFile->checkPointCopy.time,
5679+
timebuf, sizeof(timebuf))),
56765680
errhint("If this has occurred more than once some data might be corrupted"
56775681
" and you might need to choose an earlier recovery target.")));
56785682
break;
56795683

56805684
case DB_IN_PRODUCTION:
56815685
ereport(LOG,
56825686
(errmsg("database system was interrupted; last known up at %s",
5683-
str_time(ControlFile->time))));
5687+
str_time(ControlFile->time,
5688+
timebuf, sizeof(timebuf)))));
56845689
break;
56855690

56865691
default:
@@ -6325,6 +6330,12 @@ StartupXLOG(void)
63256330
*/
63266331
CompleteCommitTsInitialization();
63276332

6333+
/* Clean up EndOfWalRecoveryInfo data to appease Valgrind leak checking */
6334+
if (endOfRecoveryInfo->lastPage)
6335+
pfree(endOfRecoveryInfo->lastPage);
6336+
pfree(endOfRecoveryInfo->recoveryStopReason);
6337+
pfree(endOfRecoveryInfo);
6338+
63286339
/*
63296340
* All done with end-of-recovery actions.
63306341
*

src/backend/access/transam/xlogrecovery.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,7 @@ ShutdownWalRecovery(void)
16261626
close(readFile);
16271627
readFile = -1;
16281628
}
1629+
pfree(xlogreader->private_data);
16291630
XLogReaderFree(xlogreader);
16301631
XLogPrefetcherFree(xlogprefetcher);
16311632

src/backend/libpq/pqcomm.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,6 @@ RemoveSocketFiles(void)
858858
(void) unlink(sock_path);
859859
}
860860
/* Since we're about to exit, no need to reclaim storage */
861-
sock_paths = NIL;
862861
}
863862

864863

src/backend/libpq/pqmq.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "tcop/tcopprot.h"
2424
#include "utils/builtins.h"
2525

26-
static shm_mq_handle *pq_mq_handle;
26+
static shm_mq_handle *pq_mq_handle = NULL;
2727
static bool pq_mq_busy = false;
2828
static pid_t pq_mq_parallel_leader_pid = 0;
2929
static ProcNumber pq_mq_parallel_leader_proc_number = INVALID_PROC_NUMBER;
@@ -66,6 +66,8 @@ pq_redirect_to_shm_mq(dsm_segment *seg, shm_mq_handle *mqh)
6666
static void
6767
pq_cleanup_redirect_to_shm_mq(dsm_segment *seg, Datum arg)
6868
{
69+
if (pq_mq_handle != NULL)
70+
pfree(pq_mq_handle);
6971
pq_mq_handle = NULL;
7072
whereToSendOutput = DestNone;
7173
}
@@ -131,7 +133,10 @@ mq_putmessage(char msgtype, const char *s, size_t len)
131133
if (pq_mq_busy)
132134
{
133135
if (pq_mq_handle != NULL)
136+
{
134137
shm_mq_detach(pq_mq_handle);
138+
pfree(pq_mq_handle);
139+
}
135140
pq_mq_handle = NULL;
136141
return EOF;
137142
}
@@ -152,15 +157,14 @@ mq_putmessage(char msgtype, const char *s, size_t len)
152157
iov[1].data = s;
153158
iov[1].len = len;
154159

155-
Assert(pq_mq_handle != NULL);
156-
157160
for (;;)
158161
{
159162
/*
160163
* Immediately notify the receiver by passing force_flush as true so
161164
* that the shared memory value is updated before we send the parallel
162165
* message signal right after this.
163166
*/
167+
Assert(pq_mq_handle != NULL);
164168
result = shm_mq_sendv(pq_mq_handle, iov, 2, true, true);
165169

166170
if (pq_mq_parallel_leader_pid != 0)

src/backend/postmaster/autovacuum.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,16 @@ static AutoVacuumShmemStruct *AutoVacuumShmem;
310310
static dlist_head DatabaseList = DLIST_STATIC_INIT(DatabaseList);
311311
static MemoryContext DatabaseListCxt = NULL;
312312

313+
/*
314+
* Dummy pointer to persuade Valgrind that we've not leaked the array of
315+
* avl_dbase structs. Make it global to ensure the compiler doesn't
316+
* optimize it away.
317+
*/
318+
#ifdef USE_VALGRIND
319+
extern avl_dbase *avl_dbase_array;
320+
avl_dbase *avl_dbase_array;
321+
#endif
322+
313323
/* Pointer to my own WorkerInfo, valid on each worker */
314324
static WorkerInfo MyWorkerInfo = NULL;
315325

@@ -1020,6 +1030,10 @@ rebuild_database_list(Oid newdb)
10201030

10211031
/* put all the hash elements into an array */
10221032
dbary = palloc(nelems * sizeof(avl_dbase));
1033+
/* keep Valgrind quiet */
1034+
#ifdef USE_VALGRIND
1035+
avl_dbase_array = dbary;
1036+
#endif
10231037

10241038
i = 0;
10251039
hash_seq_init(&seq, dbhash);
@@ -2565,8 +2579,18 @@ do_autovacuum(void)
25652579

25662580
/*
25672581
* We leak table_toast_map here (among other things), but since we're
2568-
* going away soon, it's not a problem.
2582+
* going away soon, it's not a problem normally. But when using Valgrind,
2583+
* release some stuff to reduce complaints about leaked storage.
25692584
*/
2585+
#ifdef USE_VALGRIND
2586+
hash_destroy(table_toast_map);
2587+
FreeTupleDesc(pg_class_desc);
2588+
if (bstrategy)
2589+
pfree(bstrategy);
2590+
#endif
2591+
2592+
/* Run the rest in xact context, mainly to avoid Valgrind leak warnings */
2593+
MemoryContextSwitchTo(TopTransactionContext);
25702594

25712595
/*
25722596
* Update pg_database.datfrozenxid, and truncate pg_xact if possible. We

src/backend/postmaster/pmchild.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ NON_EXEC_STATIC int num_pmchild_slots = 0;
5959
*/
6060
dlist_head ActiveChildList;
6161

62+
/*
63+
* Dummy pointer to persuade Valgrind that we've not leaked the array of
64+
* PMChild structs. Make it global to ensure the compiler doesn't
65+
* optimize it away.
66+
*/
67+
#ifdef USE_VALGRIND
68+
extern PMChild *pmchild_array;
69+
PMChild *pmchild_array;
70+
#endif
71+
72+
6273
/*
6374
* MaxLivePostmasterChildren
6475
*
@@ -125,8 +136,13 @@ InitPostmasterChildSlots(void)
125136
for (int i = 0; i < BACKEND_NUM_TYPES; i++)
126137
num_pmchild_slots += pmchild_pools[i].size;
127138

128-
/* Initialize them */
139+
/* Allocate enough slots, and make sure Valgrind doesn't complain */
129140
slots = palloc(num_pmchild_slots * sizeof(PMChild));
141+
#ifdef USE_VALGRIND
142+
pmchild_array = slots;
143+
#endif
144+
145+
/* Initialize them */
130146
slotno = 0;
131147
for (int btype = 0; btype < BACKEND_NUM_TYPES; btype++)
132148
{

src/backend/replication/logical/launcher.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,8 @@ logicalrep_worker_detach(void)
790790
}
791791

792792
LWLockRelease(LogicalRepWorkerLock);
793+
794+
list_free(workers);
793795
}
794796

795797
/* Block concurrent access. */

src/backend/storage/buffer/localbuf.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,11 @@ GetLocalBufferStorage(void)
932932
num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
933933

934934
/* Buffers should be I/O aligned. */
935-
cur_block = (char *)
936-
TYPEALIGN(PG_IO_ALIGN_SIZE,
937-
MemoryContextAlloc(LocalBufferContext,
938-
num_bufs * BLCKSZ + PG_IO_ALIGN_SIZE));
935+
cur_block = MemoryContextAllocAligned(LocalBufferContext,
936+
num_bufs * BLCKSZ,
937+
PG_IO_ALIGN_SIZE,
938+
0);
939+
939940
next_buf_in_block = 0;
940941
num_bufs_in_block = num_bufs;
941942
}

src/backend/tcop/backend_startup.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ static int
492492
ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
493493
{
494494
int32 len;
495-
char *buf;
495+
char *buf = NULL;
496496
ProtocolVersion proto;
497497
MemoryContext oldcontext;
498498

@@ -516,7 +516,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
516516
* scanners, which may be less benign, but it's not really our job to
517517
* notice those.)
518518
*/
519-
return STATUS_ERROR;
519+
goto fail;
520520
}
521521

522522
if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
@@ -526,7 +526,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
526526
ereport(COMMERROR,
527527
(errcode(ERRCODE_PROTOCOL_VIOLATION),
528528
errmsg("incomplete startup packet")));
529-
return STATUS_ERROR;
529+
goto fail;
530530
}
531531

532532
len = pg_ntoh32(len);
@@ -538,7 +538,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
538538
ereport(COMMERROR,
539539
(errcode(ERRCODE_PROTOCOL_VIOLATION),
540540
errmsg("invalid length of startup packet")));
541-
return STATUS_ERROR;
541+
goto fail;
542542
}
543543

544544
/*
@@ -554,7 +554,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
554554
ereport(COMMERROR,
555555
(errcode(ERRCODE_PROTOCOL_VIOLATION),
556556
errmsg("incomplete startup packet")));
557-
return STATUS_ERROR;
557+
goto fail;
558558
}
559559
pq_endmsgread();
560560

@@ -568,7 +568,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
568568
{
569569
ProcessCancelRequestPacket(port, buf, len);
570570
/* Not really an error, but we don't want to proceed further */
571-
return STATUS_ERROR;
571+
goto fail;
572572
}
573573

574574
if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
@@ -607,14 +607,16 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
607607
ereport(COMMERROR,
608608
(errcode_for_socket_access(),
609609
errmsg("failed to send SSL negotiation response: %m")));
610-
return STATUS_ERROR; /* close the connection */
610+
goto fail; /* close the connection */
611611
}
612612

613613
#ifdef USE_SSL
614614
if (SSLok == 'S' && secure_open_server(port) == -1)
615-
return STATUS_ERROR;
615+
goto fail;
616616
#endif
617617

618+
pfree(buf);
619+
618620
/*
619621
* At this point we should have no data already buffered. If we do,
620622
* it was received before we performed the SSL handshake, so it wasn't
@@ -661,14 +663,16 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
661663
ereport(COMMERROR,
662664
(errcode_for_socket_access(),
663665
errmsg("failed to send GSSAPI negotiation response: %m")));
664-
return STATUS_ERROR; /* close the connection */
666+
goto fail; /* close the connection */
665667
}
666668

667669
#ifdef ENABLE_GSS
668670
if (GSSok == 'G' && secure_open_gssapi(port) == -1)
669-
return STATUS_ERROR;
671+
goto fail;
670672
#endif
671673

674+
pfree(buf);
675+
672676
/*
673677
* At this point we should have no data already buffered. If we do,
674678
* it was received before we performed the GSS handshake, so it wasn't
@@ -863,7 +867,16 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
863867
*/
864868
MemoryContextSwitchTo(oldcontext);
865869

870+
pfree(buf);
871+
866872
return STATUS_OK;
873+
874+
fail:
875+
/* be tidy, just to avoid Valgrind complaints */
876+
if (buf)
877+
pfree(buf);
878+
879+
return STATUS_ERROR;
867880
}
868881

869882
/*

0 commit comments

Comments
 (0)