Merge lp:~maxiberta/launchpad/deduplicate-process_exists into lp:launchpad

Proposed by Maximiliano Bertacchini
Status: Merged
Merged at revision: 18594
Proposed branch: lp:~maxiberta/launchpad/deduplicate-process_exists
Merge into: lp:launchpad
Diff against target: 204 lines (+50/-39)
5 files modified
lib/lp/scripts/utilities/killservice.py (+2/-12)
lib/lp/services/osutils.py (+16/-1)
lib/lp/services/pidfile.py (+5/-9)
lib/lp/services/sitesearch/tests/test_googleservice.py (+2/-16)
lib/lp/services/tests/test_osutils.py (+25/-1)
To merge this branch: bzr merge lp:~maxiberta/launchpad/deduplicate-process_exists
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+342150@code.launchpad.net

Commit message

Deduplicate code into lp.services.osutils.process_exists().

Description of the change

Deduplicate code into lp.services.osutils.process_exists().

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/scripts/utilities/killservice.py'
2--- lib/lp/scripts/utilities/killservice.py 2015-10-26 12:34:50 +0000
3+++ lib/lp/scripts/utilities/killservice.py 2018-03-26 21:44:39 +0000
4@@ -1,6 +1,6 @@
5 #!../bin/py
6
7-# Copyright 2009 Canonical Ltd. This software is licensed under the
8+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
9 # GNU Affero General Public License version 3 (see the file LICENSE).
10
11 # This module uses relative imports.
12@@ -17,6 +17,7 @@
13
14 from lp.services.config import config
15 from lp.services.mailman.runmailman import stop_mailman
16+from lp.services.osutils import process_exists
17 from lp.services.pidfile import (
18 get_pid,
19 pidfile_path,
20@@ -101,17 +102,6 @@
21 pass
22
23
24-def process_exists(pid):
25- """True if the given process exists."""
26- try:
27- os.getpgid(pid)
28- except OSError as x:
29- if x.errno == 3:
30- return False
31- logging.error("Unknown exception from getpgid - %s", str(x))
32- return True
33-
34-
35 def wait_for_pids(pids, wait, log):
36 """
37 Wait until all signalled processes are dead, or until we hit the
38
39=== modified file 'lib/lp/services/osutils.py'
40--- lib/lp/services/osutils.py 2017-01-11 18:12:28 +0000
41+++ lib/lp/services/osutils.py 2018-03-26 21:44:39 +0000
42@@ -1,4 +1,4 @@
43-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
44+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
45 # GNU Affero General Public License version 3 (see the file LICENSE).
46
47 """Utilities for doing the sort of thing the os module does."""
48@@ -12,6 +12,7 @@
49 'get_pid_from_file',
50 'open_for_writing',
51 'override_environ',
52+ 'process_exists',
53 'remove_if_exists',
54 'remove_tree',
55 'two_stage_kill',
56@@ -194,3 +195,17 @@
57 if os.path.isfile(filename) and os.access(filename, os.X_OK):
58 return True
59 return False
60+
61+
62+def process_exists(pid):
63+ """Return True if the specified process already exists."""
64+ try:
65+ os.kill(pid, 0)
66+ except os.error as err:
67+ if err.errno == errno.ESRCH:
68+ # All is well - the process doesn't exist.
69+ return False
70+ else:
71+ # We got a strange OSError, which we'll pass upwards.
72+ raise
73+ return True
74
75=== modified file 'lib/lp/services/pidfile.py'
76--- lib/lp/services/pidfile.py 2014-01-10 04:30:31 +0000
77+++ lib/lp/services/pidfile.py 2018-03-26 21:44:39 +0000
78@@ -1,10 +1,9 @@
79-# Copyright 2009 Canonical Ltd. This software is licensed under the
80+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
81 # GNU Affero General Public License version 3 (see the file LICENSE).
82
83 __metaclass__ = type
84
85 import atexit
86-import errno
87 import os
88 from signal import (
89 signal,
90@@ -14,6 +13,7 @@
91 import tempfile
92
93 from lp.services.config import config
94+from lp.services.osutils import process_exists
95
96
97 def pidfile_path(service_name, use_config=None):
98@@ -104,13 +104,9 @@
99 # right here at the same time. But that's sufficiently unlikely, and
100 # stale PIDs are sufficiently annoying, that it's a reasonable
101 # tradeoff.
102- try:
103- os.kill(pid, 0)
104- except OSError as e:
105- if e.errno == errno.ESRCH:
106- remove_pidfile(service_name, use_config)
107- return False
108- raise
109+ if not process_exists(pid):
110+ remove_pidfile(service_name, use_config)
111+ return False
112
113 # There's a PID file and we couldn't definitively say that the
114 # process no longer exists. Assume that we're locked.
115
116=== modified file 'lib/lp/services/sitesearch/tests/test_googleservice.py'
117--- lib/lp/services/sitesearch/tests/test_googleservice.py 2018-03-16 14:50:01 +0000
118+++ lib/lp/services/sitesearch/tests/test_googleservice.py 2018-03-26 21:44:39 +0000
119@@ -1,4 +1,4 @@
120-# Copyright 2009 Canonical Ltd. This software is licensed under the
121+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
122 # GNU Affero General Public License version 3 (see the file LICENSE).
123
124 """
125@@ -8,10 +8,10 @@
126 __metaclass__ = type
127
128
129-import errno
130 import os
131 import unittest
132
133+from lp.services.osutils import process_exists
134 from lp.services.pidfile import pidfile_path
135 from lp.services.sitesearch import googletestservice
136
137@@ -37,17 +37,3 @@
138 self.assertFalse(
139 os.path.exists(filepath),
140 "The PID file '%s' should have been deleted." % filepath)
141-
142-
143-def process_exists(pid):
144- """Return True if the specified process already exists."""
145- try:
146- os.kill(pid, 0)
147- except os.error as err:
148- if err.errno == errno.ESRCH:
149- # All is well - the process doesn't exist.
150- return False
151- else:
152- # We got a strange OSError, which we'll pass upwards.
153- raise
154- return True
155
156=== modified file 'lib/lp/services/tests/test_osutils.py'
157--- lib/lp/services/tests/test_osutils.py 2017-01-14 00:28:10 +0000
158+++ lib/lp/services/tests/test_osutils.py 2018-03-26 21:44:39 +0000
159@@ -5,16 +5,21 @@
160
161 __metaclass__ = type
162
163+import errno
164 import os
165 import tempfile
166
167-from fixtures import EnvironmentVariable
168+from fixtures import (
169+ EnvironmentVariable,
170+ MockPatch,
171+ )
172 from testtools.matchers import FileContains
173
174 from lp.services.osutils import (
175 ensure_directory_exists,
176 find_on_path,
177 open_for_writing,
178+ process_exists,
179 remove_tree,
180 write_file,
181 )
182@@ -128,3 +133,22 @@
183 write_file(os.path.join(bin_dir, "program"), "")
184 self.useFixture(EnvironmentVariable("PATH", bin_dir))
185 self.assertFalse(find_on_path("program"))
186+
187+
188+class TestProcessExists(TestCase):
189+
190+ def test_with_process_running(self):
191+ pid = os.getpid()
192+ self.assertTrue(process_exists(pid))
193+
194+ def test_with_process_not_running(self):
195+ exception = OSError()
196+ exception.errno = errno.ESRCH
197+ self.useFixture(MockPatch('os.kill', side_effect=exception))
198+ self.assertFalse(process_exists(123))
199+
200+ def test_with_unknown_error(self):
201+ exception = OSError()
202+ exception.errno = errno.ENOMEM
203+ self.useFixture(MockPatch('os.kill', side_effect=exception))
204+ self.assertRaises(OSError, process_exists, 123)