Merge lp:~salgado/launchpad/use-meliae into lp:launchpad

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: not available
Proposed branch: lp:~salgado/launchpad/use-meliae
Merge into: lp:launchpad
Diff against target: 110 lines (+68/-0)
5 files modified
lib/canonical/launchpad/webapp/configure.zcml (+5/-0)
lib/canonical/launchpad/webapp/sigdumpmem.py (+18/-0)
lib/canonical/launchpad/webapp/tests/test_sigdumpmem.py (+43/-0)
setup.py (+1/-0)
versions.cfg (+1/-0)
To merge this branch: bzr merge lp:~salgado/launchpad/use-meliae
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) Approve
Review via email: mp+21674@code.launchpad.net

Description of the change

Use https://launchpad.net/meliae to get a memory dump (out of a running process) that can be analyzed later. To test you'll need to install python-meliae (from the launchpad PPA), but once this is ready to land I'll add python-meliae to launchpad-dependencies.

To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

* Don't we need to add meliae to the buildout?
* Can we use a configurable file instead of an hardcoded one?

review: Needs Information
Revision history for this message
Guilherme Salgado (salgado) wrote :

On Thu, 2010-03-18 at 19:48 +0000, Francis J. Lacoste wrote:
> Review: Needs Information
> * Don't we need to add meliae to the buildout?

We could, but since we already have it packaged in Lucid (I just
backported the package to Karmic and Hardy) and the release tarball is
not eggified, I thought I'd go with the easiest option. After all, if
we need a newer version we can easily switch to using an egg.

> * Can we use a configurable file instead of an hardcoded one?

I considered that, but I couldn't come up with any use cases that would
require changing the file path. I also try to use config values only
for things that change between environments -- which doesn't seem to be
the case here.

--
Guilherme Salgado <email address hidden>

Revision history for this message
Francis J. Lacoste (flacoste) wrote :

On March 18, 2010, Guilherme Salgado wrote:
> On Thu, 2010-03-18 at 19:48 +0000, Francis J. Lacoste wrote:
> > Review: Needs Information
> > * Don't we need to add meliae to the buildout?
>
> We could, but since we already have it packaged in Lucid (I just
> backported the package to Karmic and Hardy) and the release tarball is
> not eggified, I thought I'd go with the easiest option. After all, if
> we need a newer version we can easily switch to using an egg

Well, it does slow down the deployment of this, since they SA will have to
review/rebuild the package for Hardy (they don't deploy from our PPA) and
install it on edge/staging before you can land this.

By not eggified, you mean it doesn't have a setup.py?

> .
>
> > * Can we use a configurable file instead of an hardcoded one?
>
> I considered that, but I couldn't come up with any use cases that would
> require changing the file path. I also try to use config values only
> for things that change between environments -- which doesn't seem to be
> the case here.

Well, a hardcoded path under /tmp is vulnerable to symlink attacks
(overwriting of arbitrary files owned by the user).

--
Francis J. Lacoste
<email address hidden>

Revision history for this message
Guilherme Salgado (salgado) wrote :

On Thu, 2010-03-18 at 20:42 +0000, Francis J. Lacoste wrote:
> On March 18, 2010, Guilherme Salgado wrote:
> > On Thu, 2010-03-18 at 19:48 +0000, Francis J. Lacoste wrote:
> > > Review: Needs Information
> > > * Don't we need to add meliae to the buildout?
> >
> > We could, but since we already have it packaged in Lucid (I just
> > backported the package to Karmic and Hardy) and the release tarball is
> > not eggified, I thought I'd go with the easiest option. After all, if
> > we need a newer version we can easily switch to using an egg
>
> Well, it does slow down the deployment of this, since they SA will have to
> review/rebuild the package for Hardy (they don't deploy from our PPA) and
> install it on edge/staging before you can land this.
>
> By not eggified, you mean it doesn't have a setup.py?

The problem was that we can't seem to use buildout to make an egg out of
it because it uses pyrex/cython. After discussing this with Gary we came
to the conclusion that the least painful option would be to provide the
eggs ourselves, for now.

>
> > .
> >
> > > * Can we use a configurable file instead of an hardcoded one?
> >
> > I considered that, but I couldn't come up with any use cases that would
> > require changing the file path. I also try to use config values only
> > for things that change between environments -- which doesn't seem to be
> > the case here.
>
> Well, a hardcoded path under /tmp is vulnerable to symlink attacks
> (overwriting of arbitrary files owned by the user).

To exploit that one would need access to the file system, right, in
which case they could just as easily read the hard-coded value from the
config (if we were using a config value). Anyway, I'm willing to move
it to a config variable if you feel strong about it.

--
Guilherme Salgado <email address hidden>

Revision history for this message
Francis J. Lacoste (flacoste) wrote :

> > >
> > > > * Can we use a configurable file instead of an hardcoded one?
> > >
> > > I considered that, but I couldn't come up with any use cases that would
> > > require changing the file path. I also try to use config values only
> > > for things that change between environments -- which doesn't seem to be
> > > the case here.
> >
> > Well, a hardcoded path under /tmp is vulnerable to symlink attacks
> > (overwriting of arbitrary files owned by the user).
>
> To exploit that one would need access to the file system, right, in
> which case they could just as easily read the hard-coded value from the
> config (if we were using a config value). Anyway, I'm willing to move
> it to a config variable if you feel strong about it.
>

OK, fine.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/webapp/configure.zcml'
2--- lib/canonical/launchpad/webapp/configure.zcml 2010-03-16 05:08:47 +0000
3+++ lib/canonical/launchpad/webapp/configure.zcml 2010-03-22 15:42:30 +0000
4@@ -740,6 +740,11 @@
5 for="zope.app.appsetup.IProcessStartingEvent"
6 handler="canonical.launchpad.webapp.sigusr2.setup_sigusr2"
7 />
8+ <subscriber
9+ for="zope.app.appsetup.IProcessStartingEvent"
10+ handler="canonical.launchpad.webapp.sigdumpmem.setup_sigdumpmem"
11+ />
12+
13
14 <!-- Confirm the database is the correct revision level -->
15 <subscriber
16
17=== added file 'lib/canonical/launchpad/webapp/sigdumpmem.py'
18--- lib/canonical/launchpad/webapp/sigdumpmem.py 1970-01-01 00:00:00 +0000
19+++ lib/canonical/launchpad/webapp/sigdumpmem.py 2010-03-22 15:42:30 +0000
20@@ -0,0 +1,18 @@
21+# Copyright 2010 Canonical Ltd. This software is licensed under the
22+# GNU Affero General Public License version 3 (see the file LICENSE).
23+
24+import signal
25+
26+from meliae import scanner
27+
28+
29+SIGDUMPMEM = signal.SIGRTMIN + 10
30+DUMP_FILE = '/tmp/launchpad-memory.dump'
31+
32+
33+def sigdumpmem_handler(signum, frame):
34+ scanner.dump_all_objects(DUMP_FILE)
35+
36+
37+def setup_sigdumpmem(event):
38+ signal.signal(SIGDUMPMEM, sigdumpmem_handler)
39
40=== added file 'lib/canonical/launchpad/webapp/tests/test_sigdumpmem.py'
41--- lib/canonical/launchpad/webapp/tests/test_sigdumpmem.py 1970-01-01 00:00:00 +0000
42+++ lib/canonical/launchpad/webapp/tests/test_sigdumpmem.py 2010-03-22 15:42:30 +0000
43@@ -0,0 +1,43 @@
44+# Copyright 2010 Canonical Ltd. This software is licensed under the
45+# GNU Affero General Public License version 3 (see the file LICENSE).
46+
47+"""Test the SIGDUMPMEM signal handler."""
48+
49+__metaclass__ = type
50+
51+import os
52+import time
53+
54+from canonical.lazr.pidfile import get_pid
55+
56+from canonical.config import config
57+from canonical.launchpad.webapp.sigdumpmem import (
58+ DUMP_FILE, SIGDUMPMEM)
59+from canonical.testing.layers import AppServerLayer
60+from lp.testing import TestCase
61+
62+
63+class SIGDUMPMEMTestCase(TestCase):
64+ layer = AppServerLayer
65+
66+ def test_sigdumpmem(self):
67+ # Remove the dump file, if one exists.
68+ if os.path.exists(DUMP_FILE):
69+ os.unlink(DUMP_FILE)
70+ self.assertFalse(os.path.exists(DUMP_FILE))
71+
72+ # Get the pid for the process spawned by the AppServerLayer, which is
73+ # the one we'll be sending the signal to.
74+ orig_instance_name = config.instance_name
75+ config.setInstance('testrunner-appserver')
76+ pid = get_pid('launchpad')
77+ config.setInstance(orig_instance_name)
78+
79+ # Send the signal and ensure the dump file is created.
80+ os.kill(pid, SIGDUMPMEM)
81+ timeout = 10
82+ start_time = time.time()
83+ while time.time() < start_time + timeout:
84+ if os.path.exists(DUMP_FILE):
85+ break
86+ self.assertTrue(os.path.exists(DUMP_FILE))
87
88=== modified file 'setup.py'
89--- setup.py 2010-01-20 22:09:26 +0000
90+++ setup.py 2010-03-22 15:42:30 +0000
91@@ -43,6 +43,7 @@
92 'lazr.uri',
93 'lazr-js',
94 'mechanize',
95+ 'meliae',
96 'mercurial',
97 'mocker',
98 'oauth',
99
100=== modified file 'versions.cfg'
101--- versions.cfg 2010-03-17 14:46:16 +0000
102+++ versions.cfg 2010-03-22 15:42:30 +0000
103@@ -36,6 +36,7 @@
104 lazr-js = 0.9.2DEVr170
105 martian = 0.11
106 mechanize = 0.1.11
107+meliae = 0.2.0.final.0
108 mercurial = 1.3.1
109 mocker = 0.10.1
110 mozrunner = 1.3.4