87 lines
2.3 KiB
Python
87 lines
2.3 KiB
Python
# -*- coding: utf-8 -
|
|
#
|
|
# This file is part of gunicorn released under the MIT license.
|
|
# See the NOTICE for more information.
|
|
|
|
import errno
|
|
import os
|
|
import tempfile
|
|
|
|
|
|
class Pidfile(object):
|
|
"""\
|
|
Manage a PID file. If a specific name is provided
|
|
it and '"%s.oldpid" % name' will be used. Otherwise
|
|
we create a temp file using os.mkstemp.
|
|
"""
|
|
|
|
def __init__(self, fname):
|
|
self.fname = fname
|
|
self.pid = None
|
|
|
|
def create(self, pid):
|
|
oldpid = self.validate()
|
|
if oldpid:
|
|
if oldpid == os.getpid():
|
|
return
|
|
msg = "Already running on PID %s (or pid file '%s' is stale)"
|
|
raise RuntimeError(msg % (oldpid, self.fname))
|
|
|
|
self.pid = pid
|
|
|
|
# Write pidfile
|
|
fdir = os.path.dirname(self.fname)
|
|
if fdir and not os.path.isdir(fdir):
|
|
raise RuntimeError("%s doesn't exist. Can't create pidfile." % fdir)
|
|
fd, fname = tempfile.mkstemp(dir=fdir)
|
|
os.write(fd, ("%s\n" % self.pid).encode('utf-8'))
|
|
if self.fname:
|
|
os.rename(fname, self.fname)
|
|
else:
|
|
self.fname = fname
|
|
os.close(fd)
|
|
|
|
# set permissions to -rw-r--r--
|
|
os.chmod(self.fname, 420)
|
|
|
|
def rename(self, path):
|
|
self.unlink()
|
|
self.fname = path
|
|
self.create(self.pid)
|
|
|
|
def unlink(self):
|
|
""" delete pidfile"""
|
|
try:
|
|
with open(self.fname, "r") as f:
|
|
pid1 = int(f.read() or 0)
|
|
|
|
if pid1 == self.pid:
|
|
os.unlink(self.fname)
|
|
except:
|
|
pass
|
|
|
|
def validate(self):
|
|
""" Validate pidfile and make it stale if needed"""
|
|
if not self.fname:
|
|
return
|
|
try:
|
|
with open(self.fname, "r") as f:
|
|
try:
|
|
wpid = int(f.read())
|
|
except ValueError:
|
|
return
|
|
|
|
try:
|
|
os.kill(wpid, 0)
|
|
return wpid
|
|
except OSError as e:
|
|
if e.args[0] == errno.EPERM:
|
|
return wpid
|
|
if e.args[0] == errno.ESRCH:
|
|
return
|
|
raise
|
|
except IOError as e:
|
|
if e.args[0] == errno.ENOENT:
|
|
return
|
|
raise
|