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

Commit a2e97cb

Browse files
committed
Fix read_relmap_file() concurrency on Windows.
Commit d8cd0c6 introduced a file rename that could fail on Windows, probably due to other backends having an open file handle to the old file of the same name. Re-arrange the locking slightly to prevent that, by making sure the open() and close() run while we hold the lock. Thomas Munro. I added an explanatory comment. Discussion: https://postgr.es/m/CA%2BhUKGLZtCTgp4NTWV-wGbR2Nyag71%3DEfYTKjDKnk%2BfkhuFMHw%40mail.gmail.com
1 parent ce3049b commit a2e97cb

File tree

1 file changed

+21
-13
lines changed

1 file changed

+21
-13
lines changed

src/backend/utils/cache/relmapper.c

+21-13
Original file line numberDiff line numberDiff line change
@@ -788,16 +788,6 @@ read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
788788

789789
Assert(elevel >= ERROR);
790790

791-
/* Open the target file. */
792-
snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
793-
RELMAPPER_FILENAME);
794-
fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
795-
if (fd < 0)
796-
ereport(elevel,
797-
(errcode_for_file_access(),
798-
errmsg("could not open file \"%s\": %m",
799-
mapfilename)));
800-
801791
/*
802792
* Grab the lock to prevent the file from being updated while we read it,
803793
* unless the caller is already holding the lock. If the file is updated
@@ -808,6 +798,24 @@ read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
808798
if (!lock_held)
809799
LWLockAcquire(RelationMappingLock, LW_SHARED);
810800

801+
/*
802+
* Open the target file.
803+
*
804+
* Because Windows isn't happy about the idea of renaming over a file
805+
* that someone has open, we only open this file after acquiring the lock,
806+
* and for the same reason, we close it before releasing the lock. That
807+
* way, by the time write_relmap_file() acquires an exclusive lock, no
808+
* one else will have it open.
809+
*/
810+
snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
811+
RELMAPPER_FILENAME);
812+
fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
813+
if (fd < 0)
814+
ereport(elevel,
815+
(errcode_for_file_access(),
816+
errmsg("could not open file \"%s\": %m",
817+
mapfilename)));
818+
811819
/* Now read the data. */
812820
pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
813821
r = read(fd, map, sizeof(RelMapFile));
@@ -825,15 +833,15 @@ read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
825833
}
826834
pgstat_report_wait_end();
827835

828-
if (!lock_held)
829-
LWLockRelease(RelationMappingLock);
830-
831836
if (CloseTransientFile(fd) != 0)
832837
ereport(elevel,
833838
(errcode_for_file_access(),
834839
errmsg("could not close file \"%s\": %m",
835840
mapfilename)));
836841

842+
if (!lock_held)
843+
LWLockRelease(RelationMappingLock);
844+
837845
/* check for correct magic number, etc */
838846
if (map->magic != RELMAPPER_FILEMAGIC ||
839847
map->num_mappings < 0 ||

0 commit comments

Comments
 (0)