~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/signals.py

  • Committer: John Arbash Meinel
  • Date: 2011-09-22 14:45:18 UTC
  • mto: This revision was merged to the branch mainline in revision 6170.
  • Revision ID: john@arbash-meinel.com-20110922144518-0d11ytg0v7clv5xk
Change the code a bit.

Now, by default, there is no global state. It is created as part of
bzrlib.smart.signals.install_sighup_handler().
That way, 99% of bzr commands won't care, only 'bzr serve' is affected.
Further, the *test suite* won't have a by-product of tons of
register/unregister calls that temporarily cache dicts and create
garbage at runtime.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
 
25
25
# I'm pretty sure this has to be global, since signal handling is per-process.
26
 
_on_sighup = weakref.WeakValueDictionary()
 
26
_on_sighup = None
27
27
# TODO: Using a dict means that the order of calls is unordered. We could use a
28
28
#       list and then do something like LIFO ordering. A dict was chosen so
29
29
#       that you could have a key to easily remove your entry. However, you
31
31
#       large cases, we shouldn't have more than 100 or so callbacks
32
32
#       registered.
33
33
def _sighup_handler(signal_number, interrupted_frame):
 
34
    if _on_sighup is None:
 
35
        return
34
36
    for ref in _on_sighup.valuerefs():
35
37
        # TODO: ignore errors here
36
38
        try:
44
46
            trace.log_exception_quietly()
45
47
 
46
48
 
47
 
# TODO: One option, we could require install_sighup_handler to be called,
48
 
#       before we allocate _on_sighup. And then register_on_hangup would become
49
 
#       a no-op if install_sighup_handler was never installed. This would help
50
 
#       us avoid creating garbage if the test suite isn't going to handle it.
51
49
def install_sighup_handler():
52
50
    """Setup a handler for the SIGHUP signal."""
53
51
    signal.signal(signal.SIGHUP, _sighup_handler)
 
52
    _setup_on_hangup_dict()
 
53
 
 
54
 
 
55
def _setup_on_hangup_dict():
 
56
    """Create something for _on_sighup.
 
57
 
 
58
    This is done when we install the sighup handler, and for tests that want to
 
59
    test the functionality. If this hasn'nt been called, then
 
60
    register_on_hangup is a no-op. As is unregister_on_hangup.
 
61
    """
 
62
    global _on_sighup
 
63
    old = _on_sighup
 
64
    _on_sighup = weakref.WeakValueDictionary()
 
65
    return old
54
66
 
55
67
 
56
68
# TODO: Should these be single-use callables? Meaning that once we've triggered
61
73
#       get fired properly. Maybe we just assume we don't have to do it?
62
74
def register_on_hangup(identifier, a_callable):
63
75
    """Register for us to call a_callable as part of a graceful shutdown."""
 
76
    if _on_sighup is None:
 
77
        return
64
78
    _on_sighup[identifier] = a_callable
65
79
 
66
80
 
67
81
def unregister_on_hangup(identifier):
68
82
    """Remove a callback from being called during sighup."""
 
83
    if _on_sighup is None:
 
84
        return
69
85
    try:
70
86
        del _on_sighup[identifier]
71
87
    except KeyboardInterrupt: