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

Lines changed: 21 additions & 13 deletions
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)
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