Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+42-14
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

+1
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)