From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Sun, 8 Feb 1998 11:10:51 -0500 From: Dave Presotto presotto@plan9.bell-labs.com Subject: [9fans] create(2)/open(2) race for file creation Topicbox-Message-UUID: 71f4c5f8-eac8-11e9-9e20-41e7f4b1d025 Message-ID: <19980208161051.n2K1RjG4iJyYI2s73sUQJ9lJG2p5DqZ3H1P5UdMHEUg@z> This is why I got ken to introduce exclusive access files. I use one as a lock for a directory/file/whatever. ------ forwarded message follows ------ >>From cse.psu.edu!owner-9fans Sat Feb 7 20:03:11 EST 1998 Received: from plan9.bell-labs.com ([135.104.8.6]) by plan9; Sat Feb 7 20:03:11 EST 1998 Received: from cse.psu.edu ([130.203.3.50]) by plan9; Sat Feb 7 20:03:10 EST 1998 Received: from localhost (majordom@localhost) by cse.psu.edu (8.8.8/8.7.3) with SMTP id TAA07964; Sat, 7 Feb 1998 19:51:49 -0500 (EST) Received: by claven.cse.psu.edu (bulk_mailer v1.5); Sat, 7 Feb 1998 19:50:41 -0500 Received: (from majordom@localhost) by cse.psu.edu (8.8.8/8.7.3) id TAA07916 for 9fans-outgoing; Sat, 7 Feb 1998 19:50:35 -0500 (EST) X-Authentication-Warning: claven.cse.psu.edu: majordom set sender to owner-9fans using -f Received: from ns.dbSystems.com (root@ns.dbsystems.com [204.178.76.1]) by cse.psu.edu (8.8.8/8.7.3) with SMTP id TAA07912 for <9fans@cse.psu.edu>; Sat, 7 Feb 1998 19:50:30 -0500 (EST) Received: (from gdb@localhost) by ns.dbSystems.com (8.6.11/8.6.9) id SAA08743 for 9fans@cse.psu.edu; Sat, 7 Feb 1998 18:27:03 -0600 Date: Sat, 7 Feb 1998 18:27:03 -0600 From: "G. David Butler" Message-Id: <199802080027.SAA08743@ns.dbSystems.com> To: cse.psu.edu!9fans Subject: [9fans] create(2)/open(2) race for file creation Sender: cse.psu.edu!owner-9fans Reply-To: cse.psu.edu!9fans Precedence: bulk What is the best way for many processes to race for a file create with only one winner? In /sys/src/9/port/chan.c we have in namec(): /* * protect against the open/create race. This is not a complete * fix. It just reduces the window. */ In man open(5) the algorithm for create(2) is: if walk(5) is good { return open(5, OTRUNC) } else { if ret = create(5) is good { return ret } else { return open(5, OTRUNC) } } The first idea would be to stat(2) the file and if that fails then create(2) (That is what ape does), but if the second process stats before the first creates... NOT! Using the fact that one can create a file O_WRITE with permissions that do not allow writing, one can use a stat(2), create(2, mode 0), chmod(2) sequence as long as the amout of time between the create and the chmod are "long enough" for the other process... NOT! One could create the file with CHEXCL then clear the flag later as long as you wait "long enough" for the other process to create(2) after the stat(2)... NOT! It would seem that what is needed is the old *NIX O_EXCL flag. Another alternative would be to change create(2) to simply call create(5) and return the results. There will need to be some cleanup of programs that assume that a create on a existing file is OK, but if that is the case it is easy to change: if ((fd = create(file, mode, perm)) < 0) { error... } to: if ((fd = create(file, mode, perm)) < 0 || (fd = open(file, mode|OTRUNC) < 0)) { error... } In those programs. Any comments? David Butler gdb@dbSystems.com