/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
1
# Copyright (C) 2007 Canonical Ltd
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
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
"""Support for running strace against the current process."""
19
2386.1.2 by John Arbash Meinel
Make sure errno is imported if we are going to use it later.
20
import errno
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
21
import os
22
import signal
23
import subprocess
24
import tempfile
25
26
# this is currently test-focused, so importing bzrlib.tests is ok. We might
27
# want to move feature to its own module though.
28
from bzrlib.tests import Feature
29
2367.1.9 by Robert Collins
Review feedback.
30
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
31
def strace(function, *args, **kwargs):
32
    """Invoke strace on function.
33
2367.1.9 by Robert Collins
Review feedback.
34
    :return: a tuple: function-result, a StraceResult.
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
35
    """
36
    # capture strace output to a file
37
    log_file = tempfile.TemporaryFile()
38
    log_file_fd = log_file.fileno()
39
    pid = os.getpid()
40
    # start strace
41
    proc = subprocess.Popen(['strace',
42
        '-f', '-r', '-tt', '-p', str(pid),
43
        ],
44
        stderr=log_file_fd,
45
        stdout=log_file_fd)
46
    # TODO? confirm its started (test suite should be sufficient)
47
    # (can loop on proc.pid, but that may not indicate started and attached.)
2367.1.9 by Robert Collins
Review feedback.
48
    result = function(*args, **kwargs)
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
49
    # stop strace
50
    os.kill(proc.pid, signal.SIGQUIT)
51
    proc.communicate()
52
    # grab the log
53
    log_file.seek(0)
54
    log = log_file.read()
55
    log_file.close()
2367.1.9 by Robert Collins
Review feedback.
56
    return result, StraceResult(log)
2367.1.7 by Robert Collins
Added ``bzrlib.strace.strace`` which will strace a single callable and
57
58
59
class StraceResult(object):
60
    """The result of stracing a function."""
61
62
    def __init__(self, raw_log):
63
        """Create a StraceResult.
64
65
        :param raw_log: The output that strace created.
66
        """
67
        self.raw_log = raw_log
68
69
70
class _StraceFeature(Feature):
71
72
    def _probe(self):
73
        try:
74
            proc = subprocess.Popen(['strace'],
75
                stderr=subprocess.PIPE,
76
                stdout=subprocess.PIPE)
77
            proc.communicate()
78
            return True
79
        except OSError, e:
80
            if e.errno == errno.ENOENT:
81
                # strace is not installed
82
                return False
83
            else:
84
                raise
85
86
    def feature_name(self):
87
        return 'strace'
88
89
StraceFeature = _StraceFeature()