Skip to content

Commit 36e4456

Browse files
committed
Fix race condition if a file is removed while pg_basebackup is running.
If a relation file was removed when the server-side counterpart of pg_basebackup was just about to open it to send it to the client, you'd get a "could not open file" error. Fix that. Backpatch to 9.1, this goes back to when pg_basebackup was introduced.
1 parent d57a973 commit 36e4456

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

src/backend/replication/basebackup.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ typedef struct
4444

4545

4646
static int64 sendDir(char *path, int basepathlen, bool sizeonly);
47-
static void sendFile(char *readfilename, char *tarfilename,
48-
struct stat * statbuf);
47+
static bool sendFile(char *readfilename, char *tarfilename,
48+
struct stat * statbuf, bool missing_ok);
4949
static void sendFileWithContent(const char *filename, const char *content);
5050
static void _tarWriteHeader(const char *filename, const char *linktarget,
5151
struct stat * statbuf);
@@ -199,7 +199,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
199199
XLOG_CONTROL_FILE)));
200200
}
201201

202-
sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf);
202+
sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false);
203203
}
204204

205205
/*
@@ -712,11 +712,18 @@ sendDir(char *path, int basepathlen, bool sizeonly)
712712
}
713713
else if (S_ISREG(statbuf.st_mode))
714714
{
715-
/* Add size, rounded up to 512byte block */
716-
size += ((statbuf.st_size + 511) & ~511);
715+
bool sent = false;
716+
717717
if (!sizeonly)
718-
sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf);
719-
size += 512; /* Size of the header of the file */
718+
sent = sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf,
719+
true);
720+
721+
if (sent || sizeonly)
722+
{
723+
/* Add size, rounded up to 512byte block */
724+
size += ((statbuf.st_size + 511) & ~511);
725+
size += 512; /* Size of the header of the file */
726+
}
720727
}
721728
else
722729
ereport(WARNING,
@@ -776,9 +783,17 @@ _tarChecksum(char *header)
776783
return sum;
777784
}
778785

779-
/* Given the member, write the TAR header & send the file */
780-
static void
781-
sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
786+
/*
787+
* Given the member, write the TAR header & send the file.
788+
*
789+
* If 'missing_ok' is true, will not throw an error if the file is not found.
790+
*
791+
* Returns true if the file was successfully sent, false if 'missing_ok',
792+
* and the file did not exist.
793+
*/
794+
static bool
795+
sendFile(char *readfilename, char *tarfilename, struct stat *statbuf,
796+
bool missing_ok)
782797
{
783798
FILE *fp;
784799
char buf[TAR_SEND_SIZE];
@@ -788,9 +803,13 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
788803

789804
fp = AllocateFile(readfilename, "rb");
790805
if (fp == NULL)
806+
{
807+
if (errno == ENOENT && missing_ok)
808+
return false;
791809
ereport(ERROR,
792810
(errcode_for_file_access(),
793811
errmsg("could not open file \"%s\": %m", readfilename)));
812+
}
794813

795814
/*
796815
* Some compilers will throw a warning knowing this test can never be true
@@ -844,6 +863,8 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
844863
}
845864

846865
FreeFile(fp);
866+
867+
return true;
847868
}
848869

849870

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