1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# Copyright 2009 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
import atexit
import os
from signal import (
signal,
SIGTERM,
)
import sys
import tempfile
from lp.services.config import config
def pidfile_path(service_name, use_config=None):
"""Return the full pidfile path for the given service
"""
if use_config is None:
use_config = config
return os.path.join(use_config.canonical.pid_dir, '%s-%s.pid' % (
use_config.instance_name, service_name
))
def make_pidfile(service_name):
"""Write the current process id to a PID file.
Also installs an atexit handler to remove the file on process termination.
Also installs a SIGTERM signal handler to remove the file on SIGTERM.
If you install your own handler, you will want to call remove_pidfile
inside it.
"""
pidfile = pidfile_path(service_name)
if os.path.exists(pidfile):
raise RuntimeError("PID file %s already exists. Already running?" %
pidfile)
atexit.register(remove_pidfile, service_name)
def remove_pidfile_handler(*ignored):
sys.exit(-1 * SIGTERM)
signal(SIGTERM, remove_pidfile_handler)
fd, tempname = tempfile.mkstemp(dir=os.path.dirname(pidfile))
outf = os.fdopen(fd, 'w')
outf.write(str(os.getpid())+'\n')
outf.flush()
outf.close()
os.rename(tempname, pidfile)
def remove_pidfile(service_name, use_config=None):
"""Remove the PID file.
This should only be needed if you are overriding the default SIGTERM
signal handler.
"""
pidfile = pidfile_path(service_name, use_config)
pid = get_pid(service_name, use_config)
if pid is None:
return
if use_config is not None or pid == os.getpid():
os.unlink(pidfile)
def get_pid(service_name, use_config=None):
"""Return the PID for the given service as an integer, or None
May raise a ValueError if the PID file is corrupt.
This method will only be needed by service or monitoring scripts.
Currently no checking is done to ensure that the process is actually
running, is healthy, or died horribly a while ago and its PID being
used by something else. What we have is probably good enough.
"""
pidfile = pidfile_path(service_name, use_config)
try:
pid = open(pidfile).read()
return int(pid)
except IOError:
return None
except ValueError:
raise ValueError("Invalid PID %s" % repr(pid))
|