Skip to content

Commit

Permalink
attempt to rename PID file when possible
Browse files Browse the repository at this point in the history
This will preserve mtime on successful renames for comparisions.
While we're at it, avoid writing the new PID until the listeners are
inherited successfully.  This can be useful to avoid accidentally
clobbering a good PID if binding the listener or building the app
(preload_app==true) fails
  • Loading branch information
Eric Wong authored and Eric Wong committed Oct 24, 2013
1 parent d90eebe commit 7d6ac0c
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions lib/unicorn/http_server.rb
Expand Up @@ -134,11 +134,22 @@ def start
# Note that signals don't actually get handled until the #join method
QUEUE_SIGS.each { |sig| trap(sig) { SIG_QUEUE << sig; awaken_master } }
trap(:CHLD) { awaken_master }
self.pid = config[:pid]

# write pid early for Mongrel compatibility if we're not inheriting sockets
# This was needed for compatibility with some health checker a long time
# ago. This unfortunately has the side effect of clobbering valid PID
# files.
self.pid = config[:pid] unless ENV["UNICORN_FD"]

self.master_pid = $$
build_app! if preload_app
bind_new_listeners!

# Assuming preload_app==false, we drop the pid file after the app is ready
# to process requests. If binding or build_app! fails with
# preload_app==true, we'll never get here and the parent will recover
self.pid = config[:pid] if ENV["UNICORN_FD"]

spawn_missing_workers
self
end
Expand Down Expand Up @@ -180,6 +191,21 @@ def logger=(obj)
Unicorn::HttpRequest::DEFAULTS["rack.logger"] = @logger = obj
end

def clobber_pid(path)
unlink_pid_safe(@pid) if @pid
if path
fp = begin
tmp = "#{File.dirname(path)}/#{rand}.#$$"
File.open(tmp, File::RDWR|File::CREAT|File::EXCL, 0644)
rescue Errno::EEXIST
retry
end
fp.syswrite("#$$\n")
File.rename(fp.path, path)
fp.close
end
end

# sets the path for the PID file of the master process
def pid=(path)
if path
Expand All @@ -194,18 +220,18 @@ def pid=(path)
"(or pid=#{path} is stale)"
end
end
unlink_pid_safe(pid) if pid

if path
fp = begin
tmp = "#{File.dirname(path)}/#{rand}.#$$"
File.open(tmp, File::RDWR|File::CREAT|File::EXCL, 0644)
rescue Errno::EEXIST
retry
# rename the old pid if posible
if @pid && path
begin
File.rename(@pid, path)
rescue Errno::ENOENT, Errno::EXDEV
# a user may have accidentally removed the original.
# Obviously cross-FS renames
clobber_pid(path)
end
fp.syswrite("#$$\n")
File.rename(fp.path, path)
fp.close
else
clobber_pid(path)
end
@pid = path
end
Expand Down

0 comments on commit 7d6ac0c

Please sign in to comment.