Merge ~cjwatson/launchpad:remove-old-signal-handlers into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: b0062d41c8ddd2e800ff2378fbc2febd3aa6bccd
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:remove-old-signal-handlers
Merge into: launchpad:master
Diff against target: 361 lines (+0/-105)
3 files modified
dev/null (+0/-80)
lib/lp/services/webapp/adapter.py (+0/-3)
lib/lp/services/webapp/configure.zcml (+0/-22)
Reviewer Review Type Date Requested Status
Cristian Gonzalez (community) Approve
Review via email: mp+405898@code.launchpad.net

Commit message

Remove old webapp SIGHUP/SIGUSR1/SIGUSR2 handlers

Description of the change

These are neither useful nor usable when running under gunicorn (because gunicorn provides similar facilities for the most part, and also installs handlers for these signals itself).

To post a comment you must log in.
Revision history for this message
Cristian Gonzalez (cristiangsp) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/services/webapp/adapter.py b/lib/lp/services/webapp/adapter.py
2index d2d1d86..1994457 100644
3--- a/lib/lp/services/webapp/adapter.py
4+++ b/lib/lp/services/webapp/adapter.py
5@@ -660,9 +660,6 @@ class LaunchpadStatementTracer:
6 if print_traceback:
7 print_list(stack)
8 sys.stderr.write("." * 70 + "\n")
9- # store the last executed statement as an attribute on the current
10- # thread
11- threading.current_thread().lp_last_sql_statement = statement
12 request_starttime = getattr(_local, 'request_start_time', None)
13 if request_starttime is None:
14 if print_traceback or self._debug_sql or log_sql is not None:
15diff --git a/lib/lp/services/webapp/configure.zcml b/lib/lp/services/webapp/configure.zcml
16index edd452c..cb5b6b4 100644
17--- a/lib/lp/services/webapp/configure.zcml
18+++ b/lib/lp/services/webapp/configure.zcml
19@@ -338,18 +338,6 @@
20 <!-- Signal handlers -->
21 <subscriber
22 for="zope.processlifetime.IProcessStarting"
23- handler="lp.services.webapp.sighup.setup_sighup"
24- />
25- <subscriber
26- for="zope.processlifetime.IProcessStarting"
27- handler="lp.services.webapp.sigusr1.setup_sigusr1"
28- />
29- <subscriber
30- for="zope.processlifetime.IProcessStarting"
31- handler="lp.services.webapp.sigusr2.setup_sigusr2"
32- />
33- <subscriber
34- for="zope.processlifetime.IProcessStarting"
35 handler="lp.services.webapp.sigdumpmem.setup_sigdumpmem"
36 />
37
38@@ -359,16 +347,6 @@
39 handler="lp.services.webapp.adapter.set_launchpad_default_timeout"
40 />
41
42- <subscriber
43- for="zope.traversing.interfaces.IBeforeTraverseEvent"
44- handler="lp.services.webapp.sigusr1.before_traverse"
45- />
46-
47- <subscriber
48- for="zope.publisher.interfaces.IEndRequestEvent"
49- handler="lp.services.webapp.sigusr1.end_request"
50- />
51-
52 <class class="lp.services.webapp.publication.LoginRoot">
53 <allow
54 attributes="publishTraverse"
55diff --git a/lib/lp/services/webapp/sighup.py b/lib/lp/services/webapp/sighup.py
56deleted file mode 100644
57index 7623bdb..0000000
58--- a/lib/lp/services/webapp/sighup.py
59+++ /dev/null
60@@ -1,25 +0,0 @@
61-# Copyright 2010 Canonical Ltd. This software is licensed under the
62-# GNU Affero General Public License version 3 (see the file LICENSE).
63-
64-"""Signal handler for SIGHUP."""
65-
66-__metaclass__ = type
67-__all__ = []
68-
69-import logging
70-import signal
71-
72-from lp.services.webapp import haproxy
73-
74-
75-def sighup_handler(signum, frame):
76- """Switch the state of the HAProxy going_down flag."""
77- haproxy.switch_going_down_flag()
78- logging.getLogger('sighup').info(
79- 'Received SIGHUP, swiched going_down flag to %s' %
80- haproxy.going_down_flag)
81-
82-
83-def setup_sighup(event):
84- """Configure the SIGHUP handler. Called at startup."""
85- signal.signal(signal.SIGHUP, sighup_handler)
86diff --git a/lib/lp/services/webapp/sigusr1.py b/lib/lp/services/webapp/sigusr1.py
87deleted file mode 100644
88index 1ef7c80..0000000
89--- a/lib/lp/services/webapp/sigusr1.py
90+++ /dev/null
91@@ -1,52 +0,0 @@
92-# Copyright 2009 Canonical Ltd. This software is licensed under the
93-# GNU Affero General Public License version 3 (see the file LICENSE).
94-
95-"""A SIGUSR1 handler for the Launchpad Web App.
96-
97-To aid debugging, we install a handler for the SIGUSR1 signal. When
98-received, a summary of the last request, recent OOPS IDs and last
99-executed SQL statement is printed for each thread.
100-"""
101-
102-import logging
103-import signal
104-import threading
105-
106-
107-def sigusr1_handler(signum, frame):
108- """Log status of running threads in response to SIGUSR1"""
109- message = ['Thread summary:']
110- for thread in threading.enumerate():
111- # if the thread has no lp_last_request attribute, it probably
112- # isn't an appserver thread.
113- if not hasattr(thread, 'lp_last_request'):
114- continue
115- message.append('\t%s' % thread.name)
116- message.append('\t\tLast Request: %s' % thread.lp_last_request)
117- message.append('\t\tMost recent OOPS IDs: %s' %
118- ', '.join(getattr(thread, 'lp_last_oops', [])))
119- message.append('\t\tLast SQL statement: %s' %
120- getattr(thread, 'lp_last_sql_statement', None))
121- logging.getLogger('sigusr1').info('\n'.join(message))
122-
123-
124-def setup_sigusr1(event):
125- """Configure the SIGUSR1 handler. Called at startup."""
126- signal.signal(signal.SIGUSR1, sigusr1_handler)
127-
128-
129-def before_traverse(event):
130- """Record the request URL (provided that the request has a URL)"""
131- request = event.request
132- threading.current_thread().lp_last_request = str(
133- getattr(request, 'URL', ''))
134-
135-
136-def end_request(event):
137- """Record the OOPS ID in the thread, if one occurred."""
138- request = event.request
139- if request.oopsid is not None:
140- thread = threading.current_thread()
141- last_oops_ids = getattr(thread, 'lp_last_oops', [])
142- # make sure the OOPS ID list has at most 5 elements
143- thread.lp_last_oops = last_oops_ids[-4:] + [request.oopsid]
144diff --git a/lib/lp/services/webapp/sigusr2.py b/lib/lp/services/webapp/sigusr2.py
145deleted file mode 100644
146index 1e6aa6c..0000000
147--- a/lib/lp/services/webapp/sigusr2.py
148+++ /dev/null
149@@ -1,25 +0,0 @@
150-# Copyright 2009 Canonical Ltd. This software is licensed under the
151-# GNU Affero General Public License version 3 (see the file LICENSE).
152-
153-"""A SIGUSR2 handler for the Launchpad Web App.
154-
155-Sending a SIGUSR2 signal to Launchpad will cause logfiles to be
156-reopened, allowing a tool like logrotate to rotate them.
157-"""
158-
159-__metaclass__ = type
160-__all__ = ['setup_sigusr2']
161-
162-import signal
163-
164-from ZConfig.components.logger.loghandler import reopenFiles
165-
166-
167-def sigusr2_handler(signum, frame):
168- "Rotate logfiles in response to SIGUSR2."""
169- reopenFiles()
170-
171-
172-def setup_sigusr2(event):
173- """Configure the SIGUSR2 handler. Called at startup."""
174- signal.signal(signal.SIGUSR2, sigusr2_handler)
175diff --git a/lib/lp/services/webapp/tests/sigusr2.py b/lib/lp/services/webapp/tests/sigusr2.py
176deleted file mode 100644
177index 5359ec6..0000000
178--- a/lib/lp/services/webapp/tests/sigusr2.py
179+++ /dev/null
180@@ -1,51 +0,0 @@
181-# Copyright 2009 Canonical Ltd. This software is licensed under the
182-# GNU Affero General Public License version 3 (see the file LICENSE).
183-
184-"""Helper for test_sigusr2.py."""
185-
186-import logging
187-import os.path
188-import signal
189-import sys
190-
191-from ZConfig.components.logger.loghandler import FileHandler
192-
193-from lp.services.webapp.sigusr2 import setup_sigusr2
194-
195-
196-def notify(step):
197- # Quick way of communicating back to the test suite for synchronization.
198- open(os.path.join(os.path.dirname(sys.argv[1]), step), 'w').write('')
199-
200-
201-_counter = 1
202-
203-
204-def sigusr1_handler(signum, frame):
205- """Emit a message"""
206- global _counter
207- logging.getLogger('').error('Message %d' % _counter)
208- notify('emit_%d' % _counter)
209- _counter += 1
210-
211-
212-_installed_handler = None
213-
214-
215-def sigusr2_handler(signum, frame):
216- _installed_handler(signum, frame)
217- notify('sigusr2')
218-
219-
220-if __name__ == '__main__':
221- logging.getLogger('').addHandler(FileHandler(sys.argv[1]))
222- signal.signal(signal.SIGUSR1, sigusr1_handler)
223-
224- # Install the SIGUSR2 handler, and wrap it so there are notifications
225- # when it is invoked.
226- setup_sigusr2(None)
227- _installed_handler = signal.signal(signal.SIGUSR2, sigusr2_handler)
228-
229- notify('ready')
230- while True:
231- signal.pause()
232diff --git a/lib/lp/services/webapp/tests/test_sighup.py b/lib/lp/services/webapp/tests/test_sighup.py
233deleted file mode 100644
234index 1c07e3b..0000000
235--- a/lib/lp/services/webapp/tests/test_sighup.py
236+++ /dev/null
237@@ -1,38 +0,0 @@
238-# Copyright 2010 Canonical Ltd. This software is licensed under the
239-# GNU Affero General Public License version 3 (see the file LICENSE).
240-
241-"""Test the SIGHUP signal handler."""
242-
243-__metaclass__ = type
244-
245-import os
246-import signal
247-
248-from lp.services.webapp import (
249- haproxy,
250- sighup,
251- )
252-from lp.testing import TestCase
253-from lp.testing.layers import FunctionalLayer
254-
255-
256-class SIGHUPTestCase(TestCase):
257- layer = FunctionalLayer
258-
259- def setUp(self):
260- TestCase.setUp(self)
261- self.original_handler = signal.getsignal(signal.SIGHUP)
262- self.addCleanup(signal.signal, signal.SIGHUP, self.original_handler)
263- sighup.setup_sighup(None)
264-
265- self.original_flag = haproxy.going_down_flag
266- self.addCleanup(haproxy.set_going_down_flag, self.original_flag)
267-
268- def test_sighup(self):
269- # Sending SIGHUP should switch the PID
270- os.kill(os.getpid(), signal.SIGHUP)
271- self.assertEqual(not self.original_flag, haproxy.going_down_flag)
272-
273- # Sending again should switch again.
274- os.kill(os.getpid(), signal.SIGHUP)
275- self.assertEqual(self.original_flag, haproxy.going_down_flag)
276diff --git a/lib/lp/services/webapp/tests/test_sigusr2.py b/lib/lp/services/webapp/tests/test_sigusr2.py
277deleted file mode 100644
278index 87dfd4e..0000000
279--- a/lib/lp/services/webapp/tests/test_sigusr2.py
280+++ /dev/null
281@@ -1,80 +0,0 @@
282-# Copyright 2009 Canonical Ltd. This software is licensed under the
283-# GNU Affero General Public License version 3 (see the file LICENSE).
284-
285-"""Test the SIGUSR2 signal handler."""
286-
287-__metaclass__ = type
288-__all__ = []
289-
290-import os.path
291-import shutil
292-import signal
293-import subprocess
294-import sys
295-import tempfile
296-import time
297-import unittest
298-
299-
300-class SIGUSR2TestCase(unittest.TestCase):
301- def setUp(self):
302- self.logdir = tempfile.mkdtemp()
303-
304- def tearDown(self):
305- shutil.rmtree(self.logdir)
306-
307- def test_sigusr2(self):
308- main_log = os.path.join(self.logdir, 'main')
309- cycled_log = os.path.join(self.logdir, 'cycled')
310-
311- helper_cmd = [
312- sys.executable,
313- os.path.join(os.path.dirname(__file__), 'sigusr2.py'),
314- main_log]
315- proc = subprocess.Popen(
316- helper_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
317- try:
318- # Wait until things have started up.
319- self.sync('ready')
320-
321- # Make the helper emit a log message.
322- os.kill(proc.pid, signal.SIGUSR1)
323- self.sync('emit_1')
324-
325- # Move the log file under the helper's feed.
326- os.rename(main_log, cycled_log)
327-
328- # Emit another log message. This will go to cycled_log
329- # as the helper hasn't reopened its logs yet.
330- os.kill(proc.pid, signal.SIGUSR1)
331- self.sync('emit_2')
332-
333- # Invoke the sigusr2 handler in the helper. This reopens
334- # the logs, so the helper will start logging to main_log
335- # again.
336- os.kill(proc.pid, signal.SIGUSR2)
337- self.sync('sigusr2')
338-
339- # Make the helper emit a log message.
340- os.kill(proc.pid, signal.SIGUSR1)
341- self.sync('emit_3')
342- finally:
343- os.kill(proc.pid, signal.SIGKILL)
344-
345- # Confirm content in the main log and the cycled log are what we
346- # expect.
347- with open(cycled_log) as f:
348- self.assertEqual(f.read(), 'Message 1\nMessage 2\n')
349- with open(main_log) as f:
350- self.assertEqual(f.read(), 'Message 3\n')
351-
352- def sync(self, step):
353- retries = 200
354- event_filename = os.path.join(self.logdir, step)
355- for i in range(retries):
356- if os.path.exists(event_filename):
357- os.unlink(event_filename)
358- return
359- time.sleep(0.3)
360- self.fail("sync step %s didn't happen after %d retries." % (
361- step, retries))

Subscribers

People subscribed via source and target branches

to status/vote changes: