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

Commit 14bc951

Browse files
committed
Fix low-probability bug in relcache startup: write_irels wrote the
pg_internal.init file in-place, which meant that if another backend started at about the same time, it might read the incomplete file. init_irels tries to guard against that, but I have now seen a crash due to reading bad data from a partly-written file. (This may indicate a kernel bug on my platform? Not sure.) Anyway, clearly the safest course is to write the new pg_internal.init file under a unique temporary filename, and rename it into place only after it's all written.
1 parent dbc9346 commit 14bc951

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

src/backend/utils/cache/relcache.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.93 2000/03/17 02:36:27 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.94 2000/03/31 19:39:22 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -33,6 +33,7 @@
3333
#include <errno.h>
3434
#include <sys/file.h>
3535
#include <fcntl.h>
36+
#include <unistd.h>
3637

3738
#include "postgres.h"
3839

@@ -2266,14 +2267,26 @@ write_irels(void)
22662267
int i;
22672268
int relno;
22682269
RelationBuildDescInfo bi;
2270+
char tempfilename[MAXPGPATH];
2271+
char finalfilename[MAXPGPATH];
2272+
2273+
/*
2274+
* We must write a temporary file and rename it into place. Otherwise,
2275+
* another backend starting at about the same time might crash trying to
2276+
* read the partially-complete file.
2277+
*/
2278+
snprintf(tempfilename, sizeof(tempfilename), "%s%c%s.%d",
2279+
DatabasePath, SEP_CHAR, RELCACHE_INIT_FILENAME, MyProcPid);
2280+
snprintf(finalfilename, sizeof(finalfilename), "%s%c%s",
2281+
DatabasePath, SEP_CHAR, RELCACHE_INIT_FILENAME);
22692282

22702283
#ifndef __CYGWIN32__
2271-
fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
2284+
fd = PathNameOpenFile(tempfilename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
22722285
#else
2273-
fd = FileNameOpenFile(RELCACHE_INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
2286+
fd = PathNameOpenFile(tempfilename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
22742287
#endif
22752288
if (fd < 0)
2276-
elog(FATAL, "cannot create init file %s", RELCACHE_INIT_FILENAME);
2289+
elog(FATAL, "cannot create init file %s", tempfilename);
22772290

22782291
FileSeek(fd, 0L, SEEK_SET);
22792292

@@ -2397,4 +2410,10 @@ write_irels(void)
23972410
}
23982411

23992412
FileClose(fd);
2413+
2414+
/*
2415+
* And rename the temp file to its final name, deleting any previously-
2416+
* existing init file.
2417+
*/
2418+
rename(tempfilename, finalfilename);
24002419
}

0 commit comments

Comments
 (0)