launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27282
[Merge] ~cjwatson/launchpad:remove-old-signal-handlers into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:remove-old-signal-handlers into launchpad:master.
Commit message:
Remove old webapp SIGHUP/SIGUSR1/SIGUSR2 handlers
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/405898
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).
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:remove-old-signal-handlers into launchpad:master.
diff --git a/lib/lp/services/webapp/adapter.py b/lib/lp/services/webapp/adapter.py
index d2d1d86..1994457 100644
--- a/lib/lp/services/webapp/adapter.py
+++ b/lib/lp/services/webapp/adapter.py
@@ -660,9 +660,6 @@ class LaunchpadStatementTracer:
if print_traceback:
print_list(stack)
sys.stderr.write("." * 70 + "\n")
- # store the last executed statement as an attribute on the current
- # thread
- threading.current_thread().lp_last_sql_statement = statement
request_starttime = getattr(_local, 'request_start_time', None)
if request_starttime is None:
if print_traceback or self._debug_sql or log_sql is not None:
diff --git a/lib/lp/services/webapp/configure.zcml b/lib/lp/services/webapp/configure.zcml
index edd452c..cb5b6b4 100644
--- a/lib/lp/services/webapp/configure.zcml
+++ b/lib/lp/services/webapp/configure.zcml
@@ -338,18 +338,6 @@
<!-- Signal handlers -->
<subscriber
for="zope.processlifetime.IProcessStarting"
- handler="lp.services.webapp.sighup.setup_sighup"
- />
- <subscriber
- for="zope.processlifetime.IProcessStarting"
- handler="lp.services.webapp.sigusr1.setup_sigusr1"
- />
- <subscriber
- for="zope.processlifetime.IProcessStarting"
- handler="lp.services.webapp.sigusr2.setup_sigusr2"
- />
- <subscriber
- for="zope.processlifetime.IProcessStarting"
handler="lp.services.webapp.sigdumpmem.setup_sigdumpmem"
/>
@@ -359,16 +347,6 @@
handler="lp.services.webapp.adapter.set_launchpad_default_timeout"
/>
- <subscriber
- for="zope.traversing.interfaces.IBeforeTraverseEvent"
- handler="lp.services.webapp.sigusr1.before_traverse"
- />
-
- <subscriber
- for="zope.publisher.interfaces.IEndRequestEvent"
- handler="lp.services.webapp.sigusr1.end_request"
- />
-
<class class="lp.services.webapp.publication.LoginRoot">
<allow
attributes="publishTraverse"
diff --git a/lib/lp/services/webapp/sighup.py b/lib/lp/services/webapp/sighup.py
deleted file mode 100644
index 7623bdb..0000000
--- a/lib/lp/services/webapp/sighup.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2010 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Signal handler for SIGHUP."""
-
-__metaclass__ = type
-__all__ = []
-
-import logging
-import signal
-
-from lp.services.webapp import haproxy
-
-
-def sighup_handler(signum, frame):
- """Switch the state of the HAProxy going_down flag."""
- haproxy.switch_going_down_flag()
- logging.getLogger('sighup').info(
- 'Received SIGHUP, swiched going_down flag to %s' %
- haproxy.going_down_flag)
-
-
-def setup_sighup(event):
- """Configure the SIGHUP handler. Called at startup."""
- signal.signal(signal.SIGHUP, sighup_handler)
diff --git a/lib/lp/services/webapp/sigusr1.py b/lib/lp/services/webapp/sigusr1.py
deleted file mode 100644
index 1ef7c80..0000000
--- a/lib/lp/services/webapp/sigusr1.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""A SIGUSR1 handler for the Launchpad Web App.
-
-To aid debugging, we install a handler for the SIGUSR1 signal. When
-received, a summary of the last request, recent OOPS IDs and last
-executed SQL statement is printed for each thread.
-"""
-
-import logging
-import signal
-import threading
-
-
-def sigusr1_handler(signum, frame):
- """Log status of running threads in response to SIGUSR1"""
- message = ['Thread summary:']
- for thread in threading.enumerate():
- # if the thread has no lp_last_request attribute, it probably
- # isn't an appserver thread.
- if not hasattr(thread, 'lp_last_request'):
- continue
- message.append('\t%s' % thread.name)
- message.append('\t\tLast Request: %s' % thread.lp_last_request)
- message.append('\t\tMost recent OOPS IDs: %s' %
- ', '.join(getattr(thread, 'lp_last_oops', [])))
- message.append('\t\tLast SQL statement: %s' %
- getattr(thread, 'lp_last_sql_statement', None))
- logging.getLogger('sigusr1').info('\n'.join(message))
-
-
-def setup_sigusr1(event):
- """Configure the SIGUSR1 handler. Called at startup."""
- signal.signal(signal.SIGUSR1, sigusr1_handler)
-
-
-def before_traverse(event):
- """Record the request URL (provided that the request has a URL)"""
- request = event.request
- threading.current_thread().lp_last_request = str(
- getattr(request, 'URL', ''))
-
-
-def end_request(event):
- """Record the OOPS ID in the thread, if one occurred."""
- request = event.request
- if request.oopsid is not None:
- thread = threading.current_thread()
- last_oops_ids = getattr(thread, 'lp_last_oops', [])
- # make sure the OOPS ID list has at most 5 elements
- thread.lp_last_oops = last_oops_ids[-4:] + [request.oopsid]
diff --git a/lib/lp/services/webapp/sigusr2.py b/lib/lp/services/webapp/sigusr2.py
deleted file mode 100644
index 1e6aa6c..0000000
--- a/lib/lp/services/webapp/sigusr2.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""A SIGUSR2 handler for the Launchpad Web App.
-
-Sending a SIGUSR2 signal to Launchpad will cause logfiles to be
-reopened, allowing a tool like logrotate to rotate them.
-"""
-
-__metaclass__ = type
-__all__ = ['setup_sigusr2']
-
-import signal
-
-from ZConfig.components.logger.loghandler import reopenFiles
-
-
-def sigusr2_handler(signum, frame):
- "Rotate logfiles in response to SIGUSR2."""
- reopenFiles()
-
-
-def setup_sigusr2(event):
- """Configure the SIGUSR2 handler. Called at startup."""
- signal.signal(signal.SIGUSR2, sigusr2_handler)
diff --git a/lib/lp/services/webapp/tests/sigusr2.py b/lib/lp/services/webapp/tests/sigusr2.py
deleted file mode 100644
index 5359ec6..0000000
--- a/lib/lp/services/webapp/tests/sigusr2.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Helper for test_sigusr2.py."""
-
-import logging
-import os.path
-import signal
-import sys
-
-from ZConfig.components.logger.loghandler import FileHandler
-
-from lp.services.webapp.sigusr2 import setup_sigusr2
-
-
-def notify(step):
- # Quick way of communicating back to the test suite for synchronization.
- open(os.path.join(os.path.dirname(sys.argv[1]), step), 'w').write('')
-
-
-_counter = 1
-
-
-def sigusr1_handler(signum, frame):
- """Emit a message"""
- global _counter
- logging.getLogger('').error('Message %d' % _counter)
- notify('emit_%d' % _counter)
- _counter += 1
-
-
-_installed_handler = None
-
-
-def sigusr2_handler(signum, frame):
- _installed_handler(signum, frame)
- notify('sigusr2')
-
-
-if __name__ == '__main__':
- logging.getLogger('').addHandler(FileHandler(sys.argv[1]))
- signal.signal(signal.SIGUSR1, sigusr1_handler)
-
- # Install the SIGUSR2 handler, and wrap it so there are notifications
- # when it is invoked.
- setup_sigusr2(None)
- _installed_handler = signal.signal(signal.SIGUSR2, sigusr2_handler)
-
- notify('ready')
- while True:
- signal.pause()
diff --git a/lib/lp/services/webapp/tests/test_sighup.py b/lib/lp/services/webapp/tests/test_sighup.py
deleted file mode 100644
index 1c07e3b..0000000
--- a/lib/lp/services/webapp/tests/test_sighup.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2010 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test the SIGHUP signal handler."""
-
-__metaclass__ = type
-
-import os
-import signal
-
-from lp.services.webapp import (
- haproxy,
- sighup,
- )
-from lp.testing import TestCase
-from lp.testing.layers import FunctionalLayer
-
-
-class SIGHUPTestCase(TestCase):
- layer = FunctionalLayer
-
- def setUp(self):
- TestCase.setUp(self)
- self.original_handler = signal.getsignal(signal.SIGHUP)
- self.addCleanup(signal.signal, signal.SIGHUP, self.original_handler)
- sighup.setup_sighup(None)
-
- self.original_flag = haproxy.going_down_flag
- self.addCleanup(haproxy.set_going_down_flag, self.original_flag)
-
- def test_sighup(self):
- # Sending SIGHUP should switch the PID
- os.kill(os.getpid(), signal.SIGHUP)
- self.assertEqual(not self.original_flag, haproxy.going_down_flag)
-
- # Sending again should switch again.
- os.kill(os.getpid(), signal.SIGHUP)
- self.assertEqual(self.original_flag, haproxy.going_down_flag)
diff --git a/lib/lp/services/webapp/tests/test_sigusr2.py b/lib/lp/services/webapp/tests/test_sigusr2.py
deleted file mode 100644
index 87dfd4e..0000000
--- a/lib/lp/services/webapp/tests/test_sigusr2.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test the SIGUSR2 signal handler."""
-
-__metaclass__ = type
-__all__ = []
-
-import os.path
-import shutil
-import signal
-import subprocess
-import sys
-import tempfile
-import time
-import unittest
-
-
-class SIGUSR2TestCase(unittest.TestCase):
- def setUp(self):
- self.logdir = tempfile.mkdtemp()
-
- def tearDown(self):
- shutil.rmtree(self.logdir)
-
- def test_sigusr2(self):
- main_log = os.path.join(self.logdir, 'main')
- cycled_log = os.path.join(self.logdir, 'cycled')
-
- helper_cmd = [
- sys.executable,
- os.path.join(os.path.dirname(__file__), 'sigusr2.py'),
- main_log]
- proc = subprocess.Popen(
- helper_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- try:
- # Wait until things have started up.
- self.sync('ready')
-
- # Make the helper emit a log message.
- os.kill(proc.pid, signal.SIGUSR1)
- self.sync('emit_1')
-
- # Move the log file under the helper's feed.
- os.rename(main_log, cycled_log)
-
- # Emit another log message. This will go to cycled_log
- # as the helper hasn't reopened its logs yet.
- os.kill(proc.pid, signal.SIGUSR1)
- self.sync('emit_2')
-
- # Invoke the sigusr2 handler in the helper. This reopens
- # the logs, so the helper will start logging to main_log
- # again.
- os.kill(proc.pid, signal.SIGUSR2)
- self.sync('sigusr2')
-
- # Make the helper emit a log message.
- os.kill(proc.pid, signal.SIGUSR1)
- self.sync('emit_3')
- finally:
- os.kill(proc.pid, signal.SIGKILL)
-
- # Confirm content in the main log and the cycled log are what we
- # expect.
- with open(cycled_log) as f:
- self.assertEqual(f.read(), 'Message 1\nMessage 2\n')
- with open(main_log) as f:
- self.assertEqual(f.read(), 'Message 3\n')
-
- def sync(self, step):
- retries = 200
- event_filename = os.path.join(self.logdir, step)
- for i in range(retries):
- if os.path.exists(event_filename):
- os.unlink(event_filename)
- return
- time.sleep(0.3)
- self.fail("sync step %s didn't happen after %d retries." % (
- step, retries))