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

Commit 058a050

Browse files
committed
Fix memory and file descriptor leaks in pg_receivexlog/pg_basebackup
When the internal loop mode was added, freeing memory and closing filedescriptors before returning became important, and a few cases in the code missed that. Fujii Masao
1 parent 84a4256 commit 058a050

File tree

2 files changed

+54
-20
lines changed

2 files changed

+54
-20
lines changed

src/bin/pg_basebackup/receivelog.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#define STREAMING_HEADER_SIZE (1+sizeof(WalDataMessageHeader))
3939
#define STREAMING_KEEPALIVE_SIZE (1+sizeof(PrimaryKeepaliveMessage))
4040

41+
/* fd for currently open WAL file */
42+
static int walfile = -1;
43+
44+
4145
/*
4246
* Open a new WAL file in the specified directory. Store the name
4347
* (not including the full directory) in namebuf. Assumes there is
@@ -96,6 +100,7 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir, char *namebu
96100
{
97101
fprintf(stderr, _("%s: could not pad WAL segment %s: %s\n"),
98102
progname, fn, strerror(errno));
103+
free(zerobuf);
99104
close(f);
100105
unlink(fn);
101106
return -1;
@@ -120,7 +125,7 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir, char *namebu
120125
* completed writing the whole segment.
121126
*/
122127
static bool
123-
close_walfile(int walfile, char *basedir, char *walname, bool segment_complete)
128+
close_walfile(char *basedir, char *walname, bool segment_complete)
124129
{
125130
off_t currpos = lseek(walfile, 0, SEEK_CUR);
126131

@@ -142,8 +147,10 @@ close_walfile(int walfile, char *basedir, char *walname, bool segment_complete)
142147
{
143148
fprintf(stderr, _("%s: could not close file %s: %s\n"),
144149
progname, walname, strerror(errno));
150+
walfile = -1;
145151
return false;
146152
}
153+
walfile = -1;
147154

148155
/*
149156
* Rename the .partial file only if we've completed writing the whole
@@ -270,7 +277,6 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
270277
char current_walfile_name[MAXPGPATH];
271278
PGresult *res;
272279
char *copybuf = NULL;
273-
int walfile = -1;
274280
int64 last_status = -1;
275281
XLogRecPtr blockpos = InvalidXLogRecPtr;
276282

@@ -315,6 +321,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
315321
{
316322
fprintf(stderr, _("%s: could not start replication: %s\n"),
317323
progname, PQresultErrorMessage(res));
324+
PQclear(res);
318325
return false;
319326
}
320327
PQclear(res);
@@ -341,9 +348,9 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
341348
*/
342349
if (stream_stop && stream_stop(blockpos, timeline, false))
343350
{
344-
if (walfile != -1)
351+
if (walfile != -1 && !close_walfile(basedir, current_walfile_name, rename_partial))
345352
/* Potential error message is written by close_walfile */
346-
return close_walfile(walfile, basedir, current_walfile_name, rename_partial);
353+
goto error;
347354
return true;
348355
}
349356

@@ -370,7 +377,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
370377
{
371378
fprintf(stderr, _("%s: could not send feedback packet: %s"),
372379
progname, PQerrorMessage(conn));
373-
return false;
380+
goto error;
374381
}
375382

376383
last_status = now;
@@ -421,14 +428,14 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
421428
{
422429
fprintf(stderr, _("%s: select() failed: %s\n"),
423430
progname, strerror(errno));
424-
return false;
431+
goto error;
425432
}
426433
/* Else there is actually data on the socket */
427434
if (PQconsumeInput(conn) == 0)
428435
{
429436
fprintf(stderr, _("%s: could not receive data from WAL stream: %s\n"),
430437
progname, PQerrorMessage(conn));
431-
return false;
438+
goto error;
432439
}
433440
continue;
434441
}
@@ -439,7 +446,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
439446
{
440447
fprintf(stderr, _("%s: could not read copy data: %s\n"),
441448
progname, PQerrorMessage(conn));
442-
return false;
449+
goto error;
443450
}
444451
if (copybuf[0] == 'k')
445452
{
@@ -451,21 +458,21 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
451458
{
452459
fprintf(stderr, _("%s: keepalive message is incorrect size: %d\n"),
453460
progname, r);
454-
return false;
461+
goto error;
455462
}
456463
continue;
457464
}
458465
else if (copybuf[0] != 'w')
459466
{
460467
fprintf(stderr, _("%s: unrecognized streaming header: \"%c\"\n"),
461468
progname, copybuf[0]);
462-
return false;
469+
goto error;
463470
}
464471
if (r < STREAMING_HEADER_SIZE + 1)
465472
{
466473
fprintf(stderr, _("%s: streaming header too small: %d\n"),
467474
progname, r);
468-
return false;
475+
goto error;
469476
}
470477

471478
/* Extract WAL location for this block */
@@ -483,7 +490,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
483490
{
484491
fprintf(stderr, _("%s: received xlog record for offset %u with no file open\n"),
485492
progname, xlogoff);
486-
return false;
493+
goto error;
487494
}
488495
}
489496
else
@@ -494,7 +501,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
494501
{
495502
fprintf(stderr, _("%s: got WAL data offset %08x, expected %08x\n"),
496503
progname, xlogoff, (int) lseek(walfile, 0, SEEK_CUR));
497-
return false;
504+
goto error;
498505
}
499506
}
500507

@@ -520,7 +527,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
520527
basedir, current_walfile_name);
521528
if (walfile == -1)
522529
/* Error logged by open_walfile */
523-
return false;
530+
goto error;
524531
}
525532

526533
if (write(walfile,
@@ -532,7 +539,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
532539
bytes_to_write,
533540
current_walfile_name,
534541
strerror(errno));
535-
return false;
542+
goto error;
536543
}
537544

538545
/* Write was successful, advance our position */
@@ -544,11 +551,10 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
544551
/* Did we reach the end of a WAL segment? */
545552
if (blockpos % XLOG_SEG_SIZE == 0)
546553
{
547-
if (!close_walfile(walfile, basedir, current_walfile_name, false))
554+
if (!close_walfile(basedir, current_walfile_name, false))
548555
/* Error message written in close_walfile() */
549-
return false;
556+
goto error;
550557

551-
walfile = -1;
552558
xlogoff = 0;
553559

554560
if (stream_stop != NULL)
@@ -577,8 +583,22 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
577583
{
578584
fprintf(stderr, _("%s: unexpected termination of replication stream: %s\n"),
579585
progname, PQresultErrorMessage(res));
580-
return false;
586+
goto error;
581587
}
582588
PQclear(res);
589+
590+
if (copybuf != NULL)
591+
PQfreemem(copybuf);
592+
if (walfile != -1 && close(walfile) != 0)
593+
fprintf(stderr, _("%s: could not close file %s: %s\n"),
594+
progname, current_walfile_name, strerror(errno));
583595
return true;
596+
597+
error:
598+
if (copybuf != NULL)
599+
PQfreemem(copybuf);
600+
if (walfile != -1 && close(walfile) != 0)
601+
fprintf(stderr, _("%s: could not close file %s: %s\n"),
602+
progname, current_walfile_name, strerror(errno));
603+
return false;
584604
}

src/bin/pg_basebackup/streamutil.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,17 @@ GetConnection(void)
143143

144144
tmpconn = PQconnectdbParams(keywords, values, true);
145145

146+
/*
147+
* If there is too little memory even to allocate the PGconn object
148+
* and PQconnectdbParams returns NULL, we call exit(1) directly.
149+
*/
150+
if (!tmpconn)
151+
{
152+
fprintf(stderr, _("%s: could not connect to server\n"),
153+
progname);
154+
exit(1);
155+
}
156+
146157
if (PQstatus(tmpconn) == CONNECTION_BAD &&
147158
PQconnectionNeedsPassword(tmpconn) &&
148159
dbgetpassword != -1)
@@ -154,8 +165,11 @@ GetConnection(void)
154165

155166
if (PQstatus(tmpconn) != CONNECTION_OK)
156167
{
157-
fprintf(stderr, _("%s: could not connect to server: %s"),
168+
fprintf(stderr, _("%s: could not connect to server: %s\n"),
158169
progname, PQerrorMessage(tmpconn));
170+
PQfinish(tmpconn);
171+
free(values);
172+
free(keywords);
159173
return NULL;
160174
}
161175

0 commit comments

Comments
 (0)