diff options
| author | Brice Figureau <brice-puppet@daysofwonder.com> | 2010-10-16 15:10:28 +0200 |
|---|---|---|
| committer | James Turnbull <james@lovedthanlost.net> | 2010-11-10 12:56:38 +1100 |
| commit | 9ba0c8a22c6f9ca856851ef6c2d38242754a7a00 (patch) | |
| tree | d88e59636def09219d5fd1b8ac159b7e91b43482 /lib/puppet | |
| parent | cb16d3dcbad47e832890fe869e3d4f9c7224434c (diff) | |
| download | puppet-9ba0c8a22c6f9ca856851ef6c2d38242754a7a00.tar.gz puppet-9ba0c8a22c6f9ca856851ef6c2d38242754a7a00.tar.xz puppet-9ba0c8a22c6f9ca856851ef6c2d38242754a7a00.zip | |
Fix #4923 - close process race when truncating existing file
Using File.open(file, "w") calls open(2) with O_CREAT|O_TRUNC which
means when the file exists it is immediately truncated.
But the file is not locked yet, so another process can either write or
read to the file, leading to file corruption.
The fix is to truncate only when the file is exclusively locked. This can
be done on some operating system with O_EXLOCK open(2) flag.
I chose the more portable option of:
* open
* flock
* truncate
* write
* close
It might also be good to flush and fsync the file after writing it,
otherwise in case of crash an incomplete file can stay on disk.
Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com>
Diffstat (limited to 'lib/puppet')
| -rw-r--r-- | lib/puppet/util/file_locking.rb | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/lib/puppet/util/file_locking.rb b/lib/puppet/util/file_locking.rb index 8b194ed83..bd0181733 100644 --- a/lib/puppet/util/file_locking.rb +++ b/lib/puppet/util/file_locking.rb @@ -34,8 +34,11 @@ module Puppet::Util::FileLocking end Puppet::Util.sync(file).synchronize(Sync::EX) do - File.open(file, "w", mode) do |rf| + File.open(file, File::Constants::CREAT | File::Constants::WRONLY, mode) do |rf| rf.lock_exclusive do |lrf| + # poor's man open(2) O_EXLOCK|O_TRUNC + lrf.seek(0, IO::SEEK_SET) + lrf.truncate(0) yield lrf end end |
