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

Commit 286af0c

Browse files
committed
When performing a base backup, check for read errors.
The old code didn't differentiate between a read error and a concurrent truncation. fread reports both of these by returning 0; you have to use feof() or ferror() to distinguish between them, which this code did not do. It might be a better idea to use read() rather than fread() here, so that we can display a less-generic error message, but I'm not sure that would qualify as a back-patchable bug fix, so just do this much for now. Jeevan Chalke, reviewed by Jeevan Ladhe and by me. Discussion: http://postgr.es/m/CA+TgmobG4ywMzL5oQq2a8YKp8x2p3p1LOMMcGqpS7aekT9+ETA@mail.gmail.com
1 parent 5599f40 commit 286af0c

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

src/backend/replication/basebackup.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ static char *statrelpath = NULL;
9090
*/
9191
#define THROTTLING_FREQUENCY 8
9292

93+
/*
94+
* Checks whether we encountered any error in fread(). fread() doesn't give
95+
* any clue what has happened, so we check with ferror(). Also, neither
96+
* fread() nor ferror() set errno, so we just throw a generic error.
97+
*/
98+
#define CHECK_FREAD_ERROR(fp, filename) \
99+
do { \
100+
if (ferror(fp)) \
101+
ereport(ERROR, \
102+
(errmsg("could not read from file \"%s\"", filename))); \
103+
} while (0)
104+
93105
/* The actual number of bytes, transfer of which may cause sleep. */
94106
static uint64 throttling_sample;
95107

@@ -543,6 +555,8 @@ perform_base_backup(basebackup_options *opt)
543555
break;
544556
}
545557

558+
CHECK_FREAD_ERROR(fp, pathbuf);
559+
546560
if (len != wal_segment_size)
547561
{
548562
CheckXLogRemoved(segno, tli);
@@ -1478,6 +1492,20 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
14781492

14791493
if (fread(buf + BLCKSZ * i, 1, BLCKSZ, fp) != BLCKSZ)
14801494
{
1495+
/*
1496+
* If we hit end-of-file, a concurrent
1497+
* truncation must have occurred, so break out
1498+
* of this loop just as if the initial fread()
1499+
* returned 0. We'll drop through to the same
1500+
* code that handles that case. (We must fix
1501+
* up cnt first, though.)
1502+
*/
1503+
if (feof(fp))
1504+
{
1505+
cnt = BLCKSZ * i;
1506+
break;
1507+
}
1508+
14811509
ereport(ERROR,
14821510
(errcode_for_file_access(),
14831511
errmsg("could not reread block %d of file \"%s\": %m",
@@ -1529,7 +1557,7 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
15291557
len += cnt;
15301558
throttle(cnt);
15311559

1532-
if (len >= statbuf->st_size)
1560+
if (feof(fp) || len >= statbuf->st_size)
15331561
{
15341562
/*
15351563
* Reached end of file. The file could be longer, if it was
@@ -1540,6 +1568,8 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
15401568
}
15411569
}
15421570

1571+
CHECK_FREAD_ERROR(fp, readfilename);
1572+
15431573
/* If the file was truncated while we were sending it, pad it with zeros */
15441574
if (len < statbuf->st_size)
15451575
{

0 commit comments

Comments
 (0)