diff options
author | Robert Haas <rhaas@postgresql.org> | 2019-09-06 08:22:32 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2019-09-06 09:01:45 -0400 |
commit | 23df8822601dce04d259fed0326ef28ecc6d1fa0 (patch) | |
tree | 29e2831e24be79f7746675f154c24e1e859457f5 /src/backend | |
parent | f4b91a50e9e6757679322c454916bcd6b1dcbc15 (diff) |
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
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/replication/basebackup.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index 73a56cbf16e..c6032fdf107 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -84,6 +84,18 @@ static char *statrelpath = NULL; */ #define THROTTLING_FREQUENCY 8 +/* + * Checks whether we encountered any error in fread(). fread() doesn't give + * any clue what has happened, so we check with ferror(). Also, neither + * fread() nor ferror() set errno, so we just throw a generic error. + */ +#define CHECK_FREAD_ERROR(fp, filename) \ +do { \ + if (ferror(fp)) \ + ereport(ERROR, \ + (errmsg("could not read from file \"%s\"", filename))); \ +} while (0) + /* The actual number of bytes, transfer of which may cause sleep. */ static uint64 throttling_sample; @@ -438,6 +450,8 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir) break; } + CHECK_FREAD_ERROR(fp, pathbuf); + if (len != XLogSegSize) { CheckXLogRemoved(segno, tli); @@ -1177,6 +1191,8 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf, } } + CHECK_FREAD_ERROR(fp, readfilename); + /* If the file was truncated while we were sending it, pad it with zeros */ if (len < statbuf->st_size) { |