~bzr-pqm/bzr/bzr.dev

5387.2.7 by John Arbash Meinel
Merge bzr.dev 5444 to resolve some small text conflicts.
1
# Copyright (C) 2007, 2009, 2010 Canonical Ltd
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
17
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
18
"""Support for running strace against the current process."""
19
6379.6.3 by Jelmer Vernooij
Use absolute_import.
20
from __future__ import absolute_import
21
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
22
import os
23
import signal
24
import subprocess
25
import tempfile
26
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
27
from bzrlib import errors
28
29
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
30
def strace(function, *args, **kwargs):
31
    """Invoke strace on function.
32
2367.1.9 by Robert Collins
Review feedback.
33
    :return: a tuple: function-result, a StraceResult.
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
34
    """
2566.3.4 by Vincent Ladeuil
Take Martin and Robert comments into account.
35
    return strace_detailed(function, args, kwargs)
36
37
38
def strace_detailed(function, args, kwargs, follow_children=True):
2566.3.1 by Vincent Ladeuil
Fix #102019 by not asking strace to follow children forks during tests.
39
    # FIXME: strace is buggy
40
    # (https://bugs.launchpad.net/ubuntu/+source/strace/+bug/103133) and the
41
    # test suite hangs if the '-f' is given to strace *and* more than one
2566.3.4 by Vincent Ladeuil
Take Martin and Robert comments into account.
42
    # thread is running. Using follow_children=False allows the test suite to
43
    # disable fork following to work around the bug.
44
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
45
    # capture strace output to a file
2394.1.1 by Andrew Bennetts
Wait for strace to attach before running the function we want to trace.
46
    log_file = tempfile.NamedTemporaryFile()
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
47
    log_file_fd = log_file.fileno()
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
48
    err_file = tempfile.NamedTemporaryFile()
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
49
    pid = os.getpid()
50
    # start strace
2566.3.1 by Vincent Ladeuil
Fix #102019 by not asking strace to follow children forks during tests.
51
    strace_cmd = ['strace', '-r', '-tt', '-p', str(pid), '-o', log_file.name]
2566.3.2 by Vincent Ladeuil
Fix typo, add comment, following Martin's review.
52
    if follow_children:
6379.6.3 by Jelmer Vernooij
Use absolute_import.
53
        strace_cmd.append('-f')
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
54
    # need to catch both stdout and stderr to work around
55
    # bug 627208
2566.3.1 by Vincent Ladeuil
Fix #102019 by not asking strace to follow children forks during tests.
56
    proc = subprocess.Popen(strace_cmd,
57
                            stdout=subprocess.PIPE,
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
58
                            stderr=err_file.fileno())
2394.1.1 by Andrew Bennetts
Wait for strace to attach before running the function we want to trace.
59
    # Wait for strace to attach
60
    attached_notice = proc.stdout.readline()
61
    # Run the function to strace
2367.1.9 by Robert Collins
Review feedback.
62
    result = function(*args, **kwargs)
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
63
    # stop strace
64
    os.kill(proc.pid, signal.SIGQUIT)
65
    proc.communicate()
66
    # grab the log
67
    log_file.seek(0)
68
    log = log_file.read()
69
    log_file.close()
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
70
    # and stderr
71
    err_file.seek(0)
72
    err_messages = err_file.read()
73
    err_file.close()
74
    # and read any errors
75
    if err_messages.startswith("attach: ptrace(PTRACE_ATTACH,"):
76
        raise StraceError(err_messages=err_messages)
77
    return result, StraceResult(log, err_messages)
78
79
80
class StraceError(errors.BzrError):
81
    
82
    _fmt = "strace failed: %(err_messages)s"
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
83
84
85
class StraceResult(object):
86
    """The result of stracing a function."""
87
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
88
    def __init__(self, raw_log, err_messages):
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
89
        """Create a StraceResult.
90
91
        :param raw_log: The output that strace created.
92
        """
93
        self.raw_log = raw_log
5398.2.1 by Martin Pool
Cope with strace not allowing you to attach to your own processes
94
        self.err_messages = err_messages
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
95
96