mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00

The formula locks used by the installer and commands like link and unlink are backed by open files and flock(). The open file descriptors are thus leaked to any subprocesses. This can result in weird behavior in programs spawned from formula that do not expect to inherit these descriptors. Fix this by setting close-on-exec on the lock file descriptors. Fixes Homebrew/homebrew#21486.
46 lines
819 B
Ruby
46 lines
819 B
Ruby
require 'fcntl'
|
|
|
|
class FormulaLock
|
|
LOCKDIR = HOMEBREW_CACHE_FORMULA
|
|
|
|
def initialize(name)
|
|
@name = name
|
|
@path = LOCKDIR.join("#{@name}.brewing")
|
|
@lockfile = nil
|
|
end
|
|
|
|
def lock
|
|
LOCKDIR.mkpath
|
|
@lockfile = get_or_create_lockfile
|
|
unless @lockfile.flock(File::LOCK_EX | File::LOCK_NB)
|
|
raise OperationInProgressError, @name
|
|
end
|
|
end
|
|
|
|
def unlock
|
|
unless @lockfile.nil? || @lockfile.closed?
|
|
@lockfile.flock(File::LOCK_UN)
|
|
@lockfile.close
|
|
end
|
|
end
|
|
|
|
def with_lock
|
|
lock
|
|
yield
|
|
ensure
|
|
unlock
|
|
end
|
|
|
|
private
|
|
|
|
def get_or_create_lockfile
|
|
if @lockfile.nil? || @lockfile.closed?
|
|
@lockfile = @path.open(File::RDWR | File::CREAT)
|
|
@lockfile.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
|
@lockfile
|
|
else
|
|
@lockfile
|
|
end
|
|
end
|
|
end
|