You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					87 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					87 lines
				
				2.3 KiB
			| 
											8 years ago
										 | # -*- 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
 |