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
=== modified file 'lib/lp/scripts/utilities/killservice.py'
--- lib/lp/scripts/utilities/killservice.py 2015-10-26 12:34:50 +0000
+++ lib/lp/scripts/utilities/killservice.py 2018-03-26 21:44:39 +0000
@@ -1,6 +1,6 @@
1#!../bin/py1#!../bin/py
22
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6# This module uses relative imports.6# This module uses relative imports.
@@ -17,6 +17,7 @@
1717
18from lp.services.config import config18from lp.services.config import config
19from lp.services.mailman.runmailman import stop_mailman19from lp.services.mailman.runmailman import stop_mailman
20from lp.services.osutils import process_exists
20from lp.services.pidfile import (21from lp.services.pidfile import (
21 get_pid,22 get_pid,
22 pidfile_path,23 pidfile_path,
@@ -101,17 +102,6 @@
101 pass102 pass
102103
103104
104def process_exists(pid):
105 """True if the given process exists."""
106 try:
107 os.getpgid(pid)
108 except OSError as x:
109 if x.errno == 3:
110 return False
111 logging.error("Unknown exception from getpgid - %s", str(x))
112 return True
113
114
115def wait_for_pids(pids, wait, log):105def wait_for_pids(pids, wait, log):
116 """106 """
117 Wait until all signalled processes are dead, or until we hit the107 Wait until all signalled processes are dead, or until we hit the
118108
=== modified file 'lib/lp/services/osutils.py'
--- lib/lp/services/osutils.py 2017-01-11 18:12:28 +0000
+++ lib/lp/services/osutils.py 2018-03-26 21:44:39 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009-2017 Canonical Ltd. This software is licensed under the1# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Utilities for doing the sort of thing the os module does."""4"""Utilities for doing the sort of thing the os module does."""
@@ -12,6 +12,7 @@
12 'get_pid_from_file',12 'get_pid_from_file',
13 'open_for_writing',13 'open_for_writing',
14 'override_environ',14 'override_environ',
15 'process_exists',
15 'remove_if_exists',16 'remove_if_exists',
16 'remove_tree',17 'remove_tree',
17 'two_stage_kill',18 'two_stage_kill',
@@ -194,3 +195,17 @@
194 if os.path.isfile(filename) and os.access(filename, os.X_OK):195 if os.path.isfile(filename) and os.access(filename, os.X_OK):
195 return True196 return True
196 return False197 return False
198
199
200def process_exists(pid):
201 """Return True if the specified process already exists."""
202 try:
203 os.kill(pid, 0)
204 except os.error as err:
205 if err.errno == errno.ESRCH:
206 # All is well - the process doesn't exist.
207 return False
208 else:
209 # We got a strange OSError, which we'll pass upwards.
210 raise
211 return True
197212
=== modified file 'lib/lp/services/pidfile.py'
--- lib/lp/services/pidfile.py 2014-01-10 04:30:31 +0000
+++ lib/lp/services/pidfile.py 2018-03-26 21:44:39 +0000
@@ -1,10 +1,9 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4__metaclass__ = type4__metaclass__ = type
55
6import atexit6import atexit
7import errno
8import os7import os
9from signal import (8from signal import (
10 signal,9 signal,
@@ -14,6 +13,7 @@
14import tempfile13import tempfile
1514
16from lp.services.config import config15from lp.services.config import config
16from lp.services.osutils import process_exists
1717
1818
19def pidfile_path(service_name, use_config=None):19def pidfile_path(service_name, use_config=None):
@@ -104,13 +104,9 @@
104 # right here at the same time. But that's sufficiently unlikely, and104 # right here at the same time. But that's sufficiently unlikely, and
105 # stale PIDs are sufficiently annoying, that it's a reasonable105 # stale PIDs are sufficiently annoying, that it's a reasonable
106 # tradeoff.106 # tradeoff.
107 try:107 if not process_exists(pid):
108 os.kill(pid, 0)108 remove_pidfile(service_name, use_config)
109 except OSError as e:109 return False
110 if e.errno == errno.ESRCH:
111 remove_pidfile(service_name, use_config)
112 return False
113 raise
114110
115 # There's a PID file and we couldn't definitively say that the111 # There's a PID file and we couldn't definitively say that the
116 # process no longer exists. Assume that we're locked.112 # process no longer exists. Assume that we're locked.
117113
=== modified file 'lib/lp/services/sitesearch/tests/test_googleservice.py'
--- lib/lp/services/sitesearch/tests/test_googleservice.py 2018-03-16 14:50:01 +0000
+++ lib/lp/services/sitesearch/tests/test_googleservice.py 2018-03-26 21:44:39 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""4"""
@@ -8,10 +8,10 @@
8__metaclass__ = type8__metaclass__ = type
99
1010
11import errno
12import os11import os
13import unittest12import unittest
1413
14from lp.services.osutils import process_exists
15from lp.services.pidfile import pidfile_path15from lp.services.pidfile import pidfile_path
16from lp.services.sitesearch import googletestservice16from lp.services.sitesearch import googletestservice
1717
@@ -37,17 +37,3 @@
37 self.assertFalse(37 self.assertFalse(
38 os.path.exists(filepath),38 os.path.exists(filepath),
39 "The PID file '%s' should have been deleted." % filepath)39 "The PID file '%s' should have been deleted." % filepath)
40
41
42def process_exists(pid):
43 """Return True if the specified process already exists."""
44 try:
45 os.kill(pid, 0)
46 except os.error as err:
47 if err.errno == errno.ESRCH:
48 # All is well - the process doesn't exist.
49 return False
50 else:
51 # We got a strange OSError, which we'll pass upwards.
52 raise
53 return True
5440
=== modified file 'lib/lp/services/tests/test_osutils.py'
--- lib/lp/services/tests/test_osutils.py 2017-01-14 00:28:10 +0000
+++ lib/lp/services/tests/test_osutils.py 2018-03-26 21:44:39 +0000
@@ -5,16 +5,21 @@
55
6__metaclass__ = type6__metaclass__ = type
77
8import errno
8import os9import os
9import tempfile10import tempfile
1011
11from fixtures import EnvironmentVariable12from fixtures import (
13 EnvironmentVariable,
14 MockPatch,
15 )
12from testtools.matchers import FileContains16from testtools.matchers import FileContains
1317
14from lp.services.osutils import (18from lp.services.osutils import (
15 ensure_directory_exists,19 ensure_directory_exists,
16 find_on_path,20 find_on_path,
17 open_for_writing,21 open_for_writing,
22 process_exists,
18 remove_tree,23 remove_tree,
19 write_file,24 write_file,
20 )25 )
@@ -128,3 +133,22 @@
128 write_file(os.path.join(bin_dir, "program"), "")133 write_file(os.path.join(bin_dir, "program"), "")
129 self.useFixture(EnvironmentVariable("PATH", bin_dir))134 self.useFixture(EnvironmentVariable("PATH", bin_dir))
130 self.assertFalse(find_on_path("program"))135 self.assertFalse(find_on_path("program"))
136
137
138class TestProcessExists(TestCase):
139
140 def test_with_process_running(self):
141 pid = os.getpid()
142 self.assertTrue(process_exists(pid))
143
144 def test_with_process_not_running(self):
145 exception = OSError()
146 exception.errno = errno.ESRCH
147 self.useFixture(MockPatch('os.kill', side_effect=exception))
148 self.assertFalse(process_exists(123))
149
150 def test_with_unknown_error(self):
151 exception = OSError()
152 exception.errno = errno.ENOMEM
153 self.useFixture(MockPatch('os.kill', side_effect=exception))
154 self.assertRaises(OSError, process_exists, 123)