Opened 12 years ago

Closed 11 years ago

#104 closed defect (invalid)

Race condition creating temporary file names for (open ... :if-exists :supersede)

Reported by: gb Owned by: gb
Priority: major Milestone:
Component: Runtime (threads, GC) Version:
Keywords: Cc:

Description

If an existing output file is opened with :IF-EXISTS :SUPERSEDE in effect, OPEN renames the original file to a temporary file name. The code which tests for uniqueness of temporary file names is subject to race conditions (e.g., it is possible that two threads/processes could both conclude that the same temporary file name was available at about the same time and rename different files to the same temporary file name, clobbering at least one original.)

Some C library routines attempt to address this by making the test for availability be "open, creating and failing if the file exists". If everything which contends for the same pathname uses that method, that avoids conflicts. It might also be possible to minimize the possibility of collisions by incorporating a representation of process/thread IDs in the generated temporary filenames.

Any scheme which tries to handle this is only viable if all contenders use the same scheme.

Change History (1)

comment:1 Changed 11 years ago by gb

  • Resolution set to invalid
  • Status changed from new to closed

There was a bug whereby :IF-EXISTS NIL didn't return NIL when the file existed; two threads could check (via PROBE-FILE) and conclude that a file didn't exist, try to create it with (OPEN ... :IF-EXISTS NIL), and both think that they'd succeeded in atomically creating a new file. (At most one thread should succeed in this case.)

:IF-EXISTS :SUPERSEDE is a different matter; CLHS requires that "a new file with the same name" be created, and encourages the implementation to preserve the file's old contents until the new stream is closed. In CCL, this is implemented by renaming the old file to a unique temporary name and creating a new file with the old file's name; there is a small time window between the rename and the creation where no file with the old file's name exists. I'm not aware of anything in the spec that requires that the old file always exist while being superseded, or anything that suggests that it always exists, and it doesn't seem correct for user code to assume otherwise.

(So, the one-time but in :IF-EXISTS NIL is closed, and the observation that :IF-EXISTS :SUPERSEDE doesn't guarantee that an existing file continues to exist at all points in time doesn't seem to describe a bug.)

Note: See TracTickets for help on using tickets.