"""$Id $ Handles signal handlers within Pydb. """ import signal def lookup_signum(name): """Find the corresponding signal number for 'name'.""" try: exec 'from signal import %s' % name except ImportError: return return eval(name) # XXX Rocky, do you think the do_* methods are confusing? I.e. that someone # will think they work the same way as the do_* method from cmd.Cmd? # I used it because print and pass are keywords and trying to strip out the # 'i' and 'a' from print and pass respectively, when this code is used in # another file is just.. mad.. 'do' made sense to me. class SigHandler: """Store information about what we do when we handle a signal, - Do we print/not print when signal is caught - Do we pass/not pass the signal to the program - Do we stop/not stop when signal is caught All the methods to change these attributes return None on error, or True or False if we have set the action (pass/print/stop) for a signal handler. """ def __init__(self, signum): # This list contains tuples made up of four items, one tuple for # every available signal number on this system. The tuples contain # (signal_num, stop, print, pass) self._sig_attr = [] for i in range(1, NSIG): try: d_handler = signal.getsignal(i) self._sig_nums.append((i, True, True, True)) except RuntimeError: # A runtime exception can be raised if we ask for the signal # handler for a signal that doesn't exist. continue def _get_sig(self, num): for i in self._sig_attr: if i[0] == num: return i[1:] def _set_sig(self, num, (st, pr, pa)): for i in self._sig_attr: if i[0] == num: self._sig_attr.pop(self._sig_attr.index(i)) self._sig_attr.append((num, st, pr, pa)) def do_stop(self, signum, change): """Change whether we stop or not when this signal is caught. If 'change' is True your program will stop when this signal happens.""" if not isinstance(change, bool): return old_attr = self._get_sig(signum) st, pr, pa = change, old_attr[1], old_attr[2] if st: pr = True self._set_sig(signum, (st, pr, pa)) return change def do_pass(self, signum, change): """Change whether we pass this signal to the program (or not) when this signal is caught. If change is True, Pydb should allow your program to see this signal. """ if not isinstance(change, bool): return old_attr = self._get_sig(signum) st, pr, pa = old_attr[0], old_attr[1], change self._set_sig(signum, (st, pr, pa)) return change # ignore is a synonym for nopass and noignore is a synonym for pass def do_ignore(self, signum, change): if not isinstance(change, bool): return self.do_pass(not change) return change def do_print(self, signum, change): """Change whether we print or not when this signal is caught.""" if not isinstance(change, bool): return old_attr = self._get_sig(signum) st, pr, pa = old_attr[0], change, old_attr[2] if not change: # noprint implies nostop st = False self._set_sig(signum, (st, pr, pa)) return change def handle(self, signum, frame): """This method is called when a signal is received.""" st, pa, pr = self._get_sig(signum) if pr: print 'Signal %d received' % self._signum if pa: # pass signal to program and stop pass