Skip to content

Commit 728ceba

Browse files
committed
Avoid leaking FDs after an fsync failure.
Fixes errors introduced in commit bc34223, as detected by Coverity. In passing, report ENOSPC for a short write while padding a new wal file in open_walfile, make certain that close_walfile closes walfile in all cases, and improve a couple of comments. Michael Paquier and Tom Lane
1 parent 3b90e38 commit 728ceba

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

src/bin/pg_basebackup/receivelog.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ mark_file_as_archived(const char *basedir, const char *fname, bool do_sync)
8686
/*
8787
* Open a new WAL file in the specified directory.
8888
*
89-
* The file will be padded to 16Mb with zeroes. The base filename (without
90-
* partial_suffix) is stored in current_walfile_name.
89+
* Returns true if OK; on failure, returns false after printing an error msg.
90+
* On success, 'walfile' is set to the FD for the file, and the base filename
91+
* (without partial_suffix) is stored in 'current_walfile_name'.
92+
*
93+
* The file will be padded to 16Mb with zeroes.
9194
*/
9295
static bool
9396
open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
@@ -127,18 +130,23 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
127130
}
128131
if (statbuf.st_size == XLogSegSize)
129132
{
130-
/* File is open and ready to use */
131-
walfile = f;
132-
133133
/*
134134
* fsync, in case of a previous crash between padding and fsyncing the
135135
* file.
136136
*/
137-
if (stream->do_sync && fsync_fname(fn, false, progname) != 0)
138-
return false;
139-
if (stream->do_sync && fsync_parent_path(fn, progname) != 0)
140-
return false;
137+
if (stream->do_sync)
138+
{
139+
if (fsync_fname(fn, false, progname) != 0 ||
140+
fsync_parent_path(fn, progname) != 0)
141+
{
142+
/* error already printed */
143+
close(f);
144+
return false;
145+
}
146+
}
141147

148+
/* File is open and ready to use */
149+
walfile = f;
142150
return true;
143151
}
144152
if (statbuf.st_size != 0)
@@ -150,12 +158,20 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
150158
return false;
151159
}
152160

153-
/* New, empty, file. So pad it to 16Mb with zeroes */
161+
/*
162+
* New, empty, file. So pad it to 16Mb with zeroes. If we fail partway
163+
* through padding, we should attempt to unlink the file on failure, so as
164+
* not to leave behind a partially-filled file.
165+
*/
154166
zerobuf = pg_malloc0(XLOG_BLCKSZ);
155167
for (bytes = 0; bytes < XLogSegSize; bytes += XLOG_BLCKSZ)
156168
{
169+
errno = 0;
157170
if (write(f, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
158171
{
172+
/* if write didn't set errno, assume problem is no disk space */
173+
if (errno == 0)
174+
errno = ENOSPC;
159175
fprintf(stderr,
160176
_("%s: could not pad transaction log file \"%s\": %s\n"),
161177
progname, fn, strerror(errno));
@@ -173,10 +189,16 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
173189
* using synchronous mode, where the file is modified and fsynced
174190
* in-place, without a directory fsync.
175191
*/
176-
if (stream->do_sync && fsync_fname(fn, false, progname) != 0)
177-
return false;
178-
if (stream->do_sync && fsync_parent_path(fn, progname) != 0)
179-
return false;
192+
if (stream->do_sync)
193+
{
194+
if (fsync_fname(fn, false, progname) != 0 ||
195+
fsync_parent_path(fn, progname) != 0)
196+
{
197+
/* error already printed */
198+
close(f);
199+
return false;
200+
}
201+
}
180202

181203
if (lseek(f, SEEK_SET, 0) != 0)
182204
{
@@ -186,6 +208,8 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
186208
close(f);
187209
return false;
188210
}
211+
212+
/* File is open and ready to use */
189213
walfile = f;
190214
return true;
191215
}
@@ -209,13 +233,17 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos)
209233
fprintf(stderr,
210234
_("%s: could not determine seek position in file \"%s\": %s\n"),
211235
progname, current_walfile_name, strerror(errno));
236+
close(walfile);
237+
walfile = -1;
212238
return false;
213239
}
214240

215241
if (stream->do_sync && fsync(walfile) != 0)
216242
{
217243
fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
218244
progname, current_walfile_name, strerror(errno));
245+
close(walfile);
246+
walfile = -1;
219247
return false;
220248
}
221249

src/common/file_utils.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ fsync_fname(const char *fname, bool isdir, const char *progname)
273273
{
274274
fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
275275
progname, fname, strerror(errno));
276+
(void) close(fd);
276277
return -1;
277278
}
278279

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy