[Python-checkins] r51427 - sandbox/trunk/pdb/patches sandbox/trunk/pdb/patches/01-08-06-pydb.diff sandbox/trunk/pdb/patches/01-08-06-pydb.diff2 sandbox/trunk/pdb/patches/01-08-06-sighandler.cmd sandbox/trunk/pdb/patches/01-08-06-sighandler.right sandbox/trunk/pdb/patches/04-07-06-patch.diff sandbox/trunk/pdb/patches/06-08-06-pydb.diff sandbox/trunk/pdb/patches/06-08-06-sighandler.cmd sandbox/trunk/pdb/patches/06-08-06-sighandler.right sandbox/trunk/pdb/patches/10-07-06-opts.diff sandbox/trunk/pdb/patches/11-08-06-pydb.diff sandbox/trunk/pdb/patches/11-08-06-sigtest.py.in sandbox/trunk/pdb/patches/11-08-06-sigtestexample.py sandbox/trunk/pdb/patches/20-08-06-threaddbg.patch sandbox/trunk/pdb/patches/24-07-06-pydb.diff sandbox/trunk/pdb/patches/24-07-06-pydb2.diff sandbox/trunk/pdb/patches/27-07-06-pydb.diff sandbox/trunk/pdb/patches/27-07-06-sighandler.py sandbox/trunk/pdb/patches/30-05-06-pdb.py sandbox/trunk/pdb/patches/31-07-06-fns.diff sandbox/trunk/pdb/patches/31-07-06-pydb.diff sandbox/trunk/pdb/patches/31-07-06-sig.diff sandbox/trunk/pdb/patches/31-07-06-sighandler.cmd sandbox/trunk/pdb/patches/31-07-06-sighandler.py sandbox/trunk/pdb/patches/31-07-06-sighandler.right sandbox/trunk/pdb/patches/31-07-06-test.py

matt.fleming python-checkins at python.org
Mon Aug 21 17:49:33 CEST 2006


Author: matt.fleming
Date: Mon Aug 21 17:49:31 2006
New Revision: 51427

Added:
   sandbox/trunk/pdb/patches/
   sandbox/trunk/pdb/patches/01-08-06-pydb.diff
   sandbox/trunk/pdb/patches/01-08-06-pydb.diff2
   sandbox/trunk/pdb/patches/01-08-06-sighandler.cmd
   sandbox/trunk/pdb/patches/01-08-06-sighandler.right
   sandbox/trunk/pdb/patches/04-07-06-patch.diff
   sandbox/trunk/pdb/patches/06-08-06-pydb.diff
   sandbox/trunk/pdb/patches/06-08-06-sighandler.cmd
   sandbox/trunk/pdb/patches/06-08-06-sighandler.right
   sandbox/trunk/pdb/patches/10-07-06-opts.diff
   sandbox/trunk/pdb/patches/11-08-06-pydb.diff
   sandbox/trunk/pdb/patches/11-08-06-sigtest.py.in
   sandbox/trunk/pdb/patches/11-08-06-sigtestexample.py
   sandbox/trunk/pdb/patches/20-08-06-threaddbg.patch
   sandbox/trunk/pdb/patches/24-07-06-pydb.diff
   sandbox/trunk/pdb/patches/24-07-06-pydb2.diff
   sandbox/trunk/pdb/patches/27-07-06-pydb.diff
   sandbox/trunk/pdb/patches/27-07-06-sighandler.py
   sandbox/trunk/pdb/patches/30-05-06-pdb.py
   sandbox/trunk/pdb/patches/31-07-06-fns.diff
   sandbox/trunk/pdb/patches/31-07-06-pydb.diff
   sandbox/trunk/pdb/patches/31-07-06-sig.diff
   sandbox/trunk/pdb/patches/31-07-06-sighandler.cmd
   sandbox/trunk/pdb/patches/31-07-06-sighandler.py
   sandbox/trunk/pdb/patches/31-07-06-sighandler.right
   sandbox/trunk/pdb/patches/31-07-06-test.py
Log:
Add the patches that I've produced over the summer, both
for pydb and my mpdb code, just so the Google Gods can see
all the stuff I've worked on for this project.


Added: sandbox/trunk/pdb/patches/01-08-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/01-08-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,237 @@
+? t.py
+? thread_script2.py
+? tpdb.py
+? tpdb2.py
+? test/sighandler.cmd
+? test/sighandler.right
+Index: pydb/sighandler.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/sighandler.py,v
+retrieving revision 1.4
+diff -u -r1.4 sighandler.py
+--- pydb/sighandler.py	1 Aug 2006 15:10:04 -0000	1.4
++++ pydb/sighandler.py	1 Aug 2006 16:53:53 -0000
+@@ -32,62 +32,24 @@
+     """
+     def __init__(self, pydb): 
+         self.pydb = pydb
+-        # This list contains tuples made up of four items, one tuple for
+-        # every signal handler we've created. The tuples contain
+-        # (signal_num, stop, print, pass)
+-        self._sig_attr = []
+-        self._sig_stop = []
+-        self._sig_print = []
+-        self._sig_pass = []
+-
+-        for sig in signal.__dict__.keys():
+-            if sig.startswith('SIG') and '_' not in sig:
+-                self._sig_attr.append(sig)
++        self._sigs = {}
+ 
+         # set up signal handling for some known signals
+-        # SIGKILL is non-maskable. Should we *really* include it here?
+-        fatal = ['SIGINT',  'SIGTRAP',  'SIGTERM', 'SIGQUIT', 'SIGILL', \
+-                 'SIGKILL', 'SIGSTOP']
++        fatal = ['SIGKILL', 'SIGSTOP']
+         ignore= ['SIGALRM', 'SIGCHLD',  'SIGURG',  'SIGIO',      'SIGVTALRM'
+                  'SIGPROF', 'SIGWINCH', 'SIGPOLL', 'SIGWAITING', 'SIGLWP',
+-                 'SIGCANCEL']
+-        for sig in self._sig_attr:
+-            if str(sig) not in fatal:
+-                num = lookup_signum(sig)
+-                if num:
+-                    if str(sig) in ignore:
+-                        self._set_sig(sig, (False, False, True))
+-                    else:
+-                        self._set_sig(sig, (True, True, True))
+-                    signal.signal(num, self.handle)
+-            else:
+-                self._set_sig(sig, (False, False, True))
+-
+-    def _get_sig(self, name):
+-        st = name in self._sig_stop
+-        pr = name in self._sig_print
+-        pa = name in self._sig_pass
+-        return (st, pr, pa)
+-
+-    def _set_sig(self, name, (st, pr, pa)):
+-        """Set the actions to be taken when a signal, specified by
+-        'name', is received.
+-        """
+-        if st:
+-            if name not in self._sig_stop:
+-                self._sig_stop.append(name)
+-        elif name in self._sig_stop:
+-                self._sig_stop.pop(self._sig_stop.index(name))
+-        if pr:
+-            if name not in self._sig_print:
+-                self._sig_print.append(name)
+-        elif name in self._sig_print:
+-                self._sig_print.pop(self._sig_print.index(name))
+-        if pa:
+-            if name not in self._sig_pass:
+-                self._sig_pass.append(name)
+-        elif name in self._sig_pass:
+-                self._sig_pass.pop(self._sig_pass.index(name))
++                 'SIGCANCEL', 'SIGTRAP', 'SIGTERM', 'SIGQUIT', 'SIGILL', \
++                 'SIGINT']
++        for sig in signal.__dict__.keys():
++            if sig.startswith('SIG') and '_' not in sig:
++                if str(sig) not in fatal:
++                    num = lookup_signum(sig)
++                    if num:
++                        if str(sig) in ignore:
++                            self._sigs[sig] = (False, False, True)
++                        else:
++                            self._sigs[sig] = (True, True, True)
++                            signal.signal(num, self.handle)
+ 
+     def info_signal(self, signame):
+         """Print information about a signal"""
+@@ -98,18 +60,14 @@
+             # This has come from pydb's info command
+             if len(signame) == 1:
+                 self.pydb.msg(header)
+-                for sig in self._sig_attr:
+-                    s = sig in self._sig_stop
+-                    pr = sig in self._sig_print
+-                    pa = sig in self._sig_pass
+-                    self.pydb.msg(fmt % (sig,s,pr,pa))
++                for sig in self._sigs.keys():
++                    st, pr, pa = self._sigs[sig]
++                    self.pydb.msg(fmt % (sig, st, pr, pa))
+             else:
+                 self.info_signal(signame[1])
+             return
+             
+-        s = signame in self._sig_stop
+-        pr = signame in self._sig_print
+-        pa = signame in self._sig_pass
++        s, pr, pa = self._sigs[signame]
+         self.pydb.msg(header)
+         self.pydb.msg(fmt % (signame, s, pr, pa))
+ 
+@@ -121,74 +79,77 @@
+             self.info_signal(['handle'])
+             return
+         args = arg.split()
+-        if args[0] in self._sig_attr:
+-            if len(args) == 1:
+-                self.info_signal(args[0])
+-                return
+-            # multiple commands might be specified, i.e. 'nopass nostop'
+-            for attr in args[1:]:
+-                if attr.startswith('no'):
+-                    on = False
+-                    attr = attr[2:]
+-                else:
+-                    on = True
+-                if attr.startswith('stop'):
+-                    self.handle_stop(args[0], on)
+-                elif attr.startswith('print'):
+-                    self.handle_print(args[0], on)
+-                elif attr.startswith('pass'):
+-                    self.handle_pass(args[0], on)
+-                else:
+-                    self.pydb.errmsg('Invalid arguments')
++        try:
++            self._sigs[args[0]]
++        except KeyError:
++            return
++        if len(args) == 1:
++            self.info_signal(args[0])
++            return
++        # multiple commands might be specified, i.e. 'nopass nostop'
++        for attr in args[1:]:
++            if attr.startswith('no'):
++                on = False
++                attr = attr[2:]
++            else:
++                on = True
++            if attr.startswith('stop'):
++                self.handle_stop(args[0], on)
++            elif attr.startswith('print'):
++                self.handle_print(args[0], on)
++            elif attr.startswith('pass'):
++                self.handle_pass(args[0], on)
++            else:
++                self.pydb.errmsg('Invalid arguments')
+ 
+-    def handle_stop(self, signum, change):
++    def handle_stop(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = change, old_attr[1], old_attr[2]
+         if st:
+             pr = True
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+-    def handle_pass(self, signum, change):
++    def handle_pass(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = old_attr[0], old_attr[1], change
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     # ignore is a synonym for nopass and noignore is a synonym for pass
+-    def handle_ignore(self, signum, change):
++    def handle_ignore(self, signame, change):
+         if not isinstance(change, bool):
+             return
+         self.handle_pass(not change)
+         return change
+ 
+-    def handle_print(self, signum, change):
++    def handle_print(self, signame, change):
+         """Change whether we print or not when this signal is caught."""
+         if not isinstance(change, bool):
+             return
+-        old_attr = self._get_sig(signum)
++        old_attr = self._sigs[signame]
+         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))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     def handle(self, signum, frame):
+         """This method is called when a signal is received."""
+         sig = lookup_signame(signum)
+-        st, pa, pr = self._get_sig(sig)
++        st, pa, pr = self._sigs[sig]
+         if pr:
+             self.pydb.msg('Program received signal %s' % sig)
+         if st:
+Index: test/Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/Makefile.am,v
+retrieving revision 1.17
+diff -u -r1.17 Makefile.am
+--- test/Makefile.am	28 Jul 2006 00:47:47 -0000	1.17
++++ test/Makefile.am	1 Aug 2006 16:53:53 -0000
+@@ -28,6 +28,8 @@
+ 	run.right       \
+ 	run2.cmd        \
+ 	run2.right      \
++	sighandler.cmd  \
++	sighandle.right \
+ 	test.py         \
+ 	trace-2.5.right \
+ 	trace.py        \

Added: sandbox/trunk/pdb/patches/01-08-06-pydb.diff2
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/01-08-06-pydb.diff2	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,255 @@
+? t.py
+? thread_script2.py
+? tpdb.py
+? tpdb2.py
+? test/sighandler.cmd
+? test/sighandler.right
+Index: pydb/sighandler.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/sighandler.py,v
+retrieving revision 1.4
+diff -u -r1.4 sighandler.py
+--- pydb/sighandler.py	1 Aug 2006 15:10:04 -0000	1.4
++++ pydb/sighandler.py	1 Aug 2006 18:08:56 -0000
+@@ -18,6 +18,8 @@
+     else:
+         return None
+ 
++fatal_signals = ['SIGKILL', 'SIGSTOP']
++
+ class SigHandler:
+ 
+     """Store information about what we do when we handle a signal,
+@@ -32,62 +34,27 @@
+     """
+     def __init__(self, pydb): 
+         self.pydb = pydb
+-        # This list contains tuples made up of four items, one tuple for
+-        # every signal handler we've created. The tuples contain
+-        # (signal_num, stop, print, pass)
+-        self._sig_attr = []
+-        self._sig_stop = []
+-        self._sig_print = []
+-        self._sig_pass = []
+-
+-        for sig in signal.__dict__.keys():
+-            if sig.startswith('SIG') and '_' not in sig:
+-                self._sig_attr.append(sig)
++        self._sigs = {}
+ 
+         # set up signal handling for some known signals
+-        # SIGKILL is non-maskable. Should we *really* include it here?
+-        fatal = ['SIGINT',  'SIGTRAP',  'SIGTERM', 'SIGQUIT', 'SIGILL', \
+-                 'SIGKILL', 'SIGSTOP']
+         ignore= ['SIGALRM', 'SIGCHLD',  'SIGURG',  'SIGIO',      'SIGVTALRM'
+                  'SIGPROF', 'SIGWINCH', 'SIGPOLL', 'SIGWAITING', 'SIGLWP',
+-                 'SIGCANCEL']
+-        for sig in self._sig_attr:
+-            if str(sig) not in fatal:
+-                num = lookup_signum(sig)
+-                if num:
+-                    if str(sig) in ignore:
+-                        self._set_sig(sig, (False, False, True))
+-                    else:
+-                        self._set_sig(sig, (True, True, True))
+-                    signal.signal(num, self.handle)
+-            else:
+-                self._set_sig(sig, (False, False, True))
+-
+-    def _get_sig(self, name):
+-        st = name in self._sig_stop
+-        pr = name in self._sig_print
+-        pa = name in self._sig_pass
+-        return (st, pr, pa)
+-
+-    def _set_sig(self, name, (st, pr, pa)):
+-        """Set the actions to be taken when a signal, specified by
+-        'name', is received.
+-        """
+-        if st:
+-            if name not in self._sig_stop:
+-                self._sig_stop.append(name)
+-        elif name in self._sig_stop:
+-                self._sig_stop.pop(self._sig_stop.index(name))
+-        if pr:
+-            if name not in self._sig_print:
+-                self._sig_print.append(name)
+-        elif name in self._sig_print:
+-                self._sig_print.pop(self._sig_print.index(name))
+-        if pa:
+-            if name not in self._sig_pass:
+-                self._sig_pass.append(name)
+-        elif name in self._sig_pass:
+-                self._sig_pass.pop(self._sig_pass.index(name))
++                 'SIGCANCEL', 'SIGTRAP', 'SIGTERM', 'SIGQUIT', 'SIGILL', \
++                 'SIGINT']
++        for sig in signal.__dict__.keys():
++            if sig.startswith('SIG') and '_' not in sig:
++                if str(sig) not in fatal_signals:
++                    num = lookup_signum(sig)
++                    if num:
++                        if str(sig) in ignore:
++                            self._sigs[sig] = (False, False, True)
++                        else:
++                            self._sigs[sig] = (True, True, True)
++                            signal.signal(num, self.handle)
++                else:
++                    # Make an entry in the _sig dict for these signals
++                    # even though they cannot be ignored or caught.
++                    self._sigs[sig] = (False, False, True)
+ 
+     def info_signal(self, signame):
+         """Print information about a signal"""
+@@ -98,18 +65,14 @@
+             # This has come from pydb's info command
+             if len(signame) == 1:
+                 self.pydb.msg(header)
+-                for sig in self._sig_attr:
+-                    s = sig in self._sig_stop
+-                    pr = sig in self._sig_print
+-                    pa = sig in self._sig_pass
+-                    self.pydb.msg(fmt % (sig,s,pr,pa))
++                for sig in self._sigs.keys():
++                    st, pr, pa = self._sigs[sig]
++                    self.pydb.msg(fmt % (sig, st, pr, pa))
+             else:
+                 self.info_signal(signame[1])
+             return
+             
+-        s = signame in self._sig_stop
+-        pr = signame in self._sig_print
+-        pa = signame in self._sig_pass
++        s, pr, pa = self._sigs[signame]
+         self.pydb.msg(header)
+         self.pydb.msg(fmt % (signame, s, pr, pa))
+ 
+@@ -121,74 +84,83 @@
+             self.info_signal(['handle'])
+             return
+         args = arg.split()
+-        if args[0] in self._sig_attr:
+-            if len(args) == 1:
+-                self.info_signal(args[0])
+-                return
+-            # multiple commands might be specified, i.e. 'nopass nostop'
+-            for attr in args[1:]:
+-                if attr.startswith('no'):
+-                    on = False
+-                    attr = attr[2:]
+-                else:
+-                    on = True
+-                if attr.startswith('stop'):
+-                    self.handle_stop(args[0], on)
+-                elif attr.startswith('print'):
+-                    self.handle_print(args[0], on)
+-                elif attr.startswith('pass'):
+-                    self.handle_pass(args[0], on)
+-                else:
+-                    self.pydb.errmsg('Invalid arguments')
++        try:
++            self._sigs[args[0]]
++        except KeyError:
++            return
++        if len(args) == 1:
++            self.info_signal(args[0])
++            return
++        
++        # We can display information about 'fatal' signals, but not
++        # change their actions.
++        if args[0] in fatal_signals:
++            return
++
++        # multiple commands might be specified, i.e. 'nopass nostop'
++        for attr in args[1:]:
++            if attr.startswith('no'):
++                on = False
++                attr = attr[2:]
++            else:
++                on = True
++            if attr.startswith('stop'):
++                self.handle_stop(args[0], on)
++            elif attr.startswith('print'):
++                self.handle_print(args[0], on)
++            elif attr.startswith('pass'):
++                self.handle_pass(args[0], on)
++            else:
++                self.pydb.errmsg('Invalid arguments')
+ 
+-    def handle_stop(self, signum, change):
++    def handle_stop(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = change, old_attr[1], old_attr[2]
+         if st:
+             pr = True
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+-    def handle_pass(self, signum, change):
++    def handle_pass(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = old_attr[0], old_attr[1], change
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     # ignore is a synonym for nopass and noignore is a synonym for pass
+-    def handle_ignore(self, signum, change):
++    def handle_ignore(self, signame, change):
+         if not isinstance(change, bool):
+             return
+         self.handle_pass(not change)
+         return change
+ 
+-    def handle_print(self, signum, change):
++    def handle_print(self, signame, change):
+         """Change whether we print or not when this signal is caught."""
+         if not isinstance(change, bool):
+             return
+-        old_attr = self._get_sig(signum)
++        old_attr = self._sigs[signame]
+         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))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     def handle(self, signum, frame):
+         """This method is called when a signal is received."""
+         sig = lookup_signame(signum)
+-        st, pa, pr = self._get_sig(sig)
++        st, pa, pr = self._sigs[sig]
+         if pr:
+             self.pydb.msg('Program received signal %s' % sig)
+         if st:
+Index: test/Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/Makefile.am,v
+retrieving revision 1.17
+diff -u -r1.17 Makefile.am
+--- test/Makefile.am	28 Jul 2006 00:47:47 -0000	1.17
++++ test/Makefile.am	1 Aug 2006 18:08:56 -0000
+@@ -28,6 +28,8 @@
+ 	run.right       \
+ 	run2.cmd        \
+ 	run2.right      \
++	sighandler.cmd  \
++	sighandle.right \
+ 	test.py         \
+ 	trace-2.5.right \
+ 	trace.py        \

Added: sandbox/trunk/pdb/patches/01-08-06-sighandler.cmd
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/01-08-06-sighandler.cmd	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,16 @@
+info signal
+info handle
+handle SIGINT
+handle SIGINT stop pass noprint
+handle SIGINT
+handle SIGINT print
+handle SIGINT
+handle SIGINT nopass noprint nostop
+handle SIGINT
+info signal SIGINT
+# try changing fatal signal handlers (which are unchangable)
+handle SIGKILL stop
+handle SIGKILL
+handle SIGSTOP print
+handle SIGSTOP
+quit

Added: sandbox/trunk/pdb/patches/01-08-06-sighandler.right
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/01-08-06-sighandler.right	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,91 @@
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGWINCH      False	False	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGCONT       True	True	True
+SIGPROF       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         False	False	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGUSR2       True	True	True
+SIGABRT       True	True	True
+SIGALRM       False	False	True
+SIGXFSZ       True	True	True
+SIGCHLD       False	False	True
+SIGPIPE       True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        False	False	True
+SIGPWR        True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+SIGTTIN       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGWINCH      False	False	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGCONT       True	True	True
+SIGPROF       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         False	False	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGUSR2       True	True	True
+SIGABRT       True	True	True
+SIGALRM       False	False	True
+SIGXFSZ       True	True	True
+SIGCHLD       False	False	True
+SIGPIPE       True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        False	False	True
+SIGPWR        True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+SIGTTIN       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False
+Signal        Stop	Print	Pass to program
+
+SIGKILL       False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGSTOP       False	False	True

Added: sandbox/trunk/pdb/patches/04-07-06-patch.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/04-07-06-patch.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,36 @@
+? configure.lineno
+? patch.diff
+Index: pydb/fns.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/fns.py,v
+retrieving revision 1.8
+diff -u -r1.8 fns.py
+--- pydb/fns.py	26 Jun 2006 12:30:18 -0000	1.8
++++ pydb/fns.py	3 Jul 2006 23:41:40 -0000
+@@ -228,7 +228,9 @@
+ 
+     if opts.output:
+         try: 
+-            sys.stdout = open(opts.output, 'w')
++            pydb.stdout = open(opts.output, 'w')
++            # XXX Redirecting sys.stdout is fine for debugging purposes
++            sys.stdout = pydb.stdout
+         except IOError, (errno, strerror):
+             print "I/O in opening debugger output file %s" % opts.output
+             print "error(%s): %s" % (errno, strerror)
+Index: pydb/pydbcmd.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/pydbcmd.py,v
+retrieving revision 1.20
+diff -u -r1.20 pydbcmd.py
+--- pydb/pydbcmd.py	18 Jun 2006 22:40:10 -0000	1.20
++++ pydb/pydbcmd.py	3 Jul 2006 23:41:40 -0000
+@@ -285,7 +285,7 @@
+             do_print = not self.logging_redirect
+         if do_print:
+             if out is None:
+-                out = sys.stdout
++                out = self.stdout
+             print >> out, msg,
+ 
+     def precmd(self, line):

Added: sandbox/trunk/pdb/patches/06-08-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/06-08-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,255 @@
+? t.py
+? thread_script2.py
+? tpdb.py
+? tpdb2.py
+? test/sighandler.cmd
+? test/sighandler.right
+Index: pydb/sighandler.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/sighandler.py,v
+retrieving revision 1.4
+diff -u -r1.4 sighandler.py
+--- pydb/sighandler.py	1 Aug 2006 15:10:04 -0000	1.4
++++ pydb/sighandler.py	1 Aug 2006 18:08:56 -0000
+@@ -18,6 +18,8 @@
+     else:
+         return None
+ 
++fatal_signals = ['SIGKILL', 'SIGSTOP']
++
+ class SigHandler:
+ 
+     """Store information about what we do when we handle a signal,
+@@ -32,62 +34,27 @@
+     """
+     def __init__(self, pydb): 
+         self.pydb = pydb
+-        # This list contains tuples made up of four items, one tuple for
+-        # every signal handler we've created. The tuples contain
+-        # (signal_num, stop, print, pass)
+-        self._sig_attr = []
+-        self._sig_stop = []
+-        self._sig_print = []
+-        self._sig_pass = []
+-
+-        for sig in signal.__dict__.keys():
+-            if sig.startswith('SIG') and '_' not in sig:
+-                self._sig_attr.append(sig)
++        self._sigs = {}
+ 
+         # set up signal handling for some known signals
+-        # SIGKILL is non-maskable. Should we *really* include it here?
+-        fatal = ['SIGINT',  'SIGTRAP',  'SIGTERM', 'SIGQUIT', 'SIGILL', \
+-                 'SIGKILL', 'SIGSTOP']
+         ignore= ['SIGALRM', 'SIGCHLD',  'SIGURG',  'SIGIO',      'SIGVTALRM'
+                  'SIGPROF', 'SIGWINCH', 'SIGPOLL', 'SIGWAITING', 'SIGLWP',
+-                 'SIGCANCEL']
+-        for sig in self._sig_attr:
+-            if str(sig) not in fatal:
+-                num = lookup_signum(sig)
+-                if num:
+-                    if str(sig) in ignore:
+-                        self._set_sig(sig, (False, False, True))
+-                    else:
+-                        self._set_sig(sig, (True, True, True))
+-                    signal.signal(num, self.handle)
+-            else:
+-                self._set_sig(sig, (False, False, True))
+-
+-    def _get_sig(self, name):
+-        st = name in self._sig_stop
+-        pr = name in self._sig_print
+-        pa = name in self._sig_pass
+-        return (st, pr, pa)
+-
+-    def _set_sig(self, name, (st, pr, pa)):
+-        """Set the actions to be taken when a signal, specified by
+-        'name', is received.
+-        """
+-        if st:
+-            if name not in self._sig_stop:
+-                self._sig_stop.append(name)
+-        elif name in self._sig_stop:
+-                self._sig_stop.pop(self._sig_stop.index(name))
+-        if pr:
+-            if name not in self._sig_print:
+-                self._sig_print.append(name)
+-        elif name in self._sig_print:
+-                self._sig_print.pop(self._sig_print.index(name))
+-        if pa:
+-            if name not in self._sig_pass:
+-                self._sig_pass.append(name)
+-        elif name in self._sig_pass:
+-                self._sig_pass.pop(self._sig_pass.index(name))
++                 'SIGCANCEL', 'SIGTRAP', 'SIGTERM', 'SIGQUIT', 'SIGILL', \
++                 'SIGINT']
++        for sig in signal.__dict__.keys():
++            if sig.startswith('SIG') and '_' not in sig:
++                if str(sig) not in fatal_signals:
++                    num = lookup_signum(sig)
++                    if num:
++                        if str(sig) in ignore:
++                            self._sigs[sig] = (False, False, True)
++                        else:
++                            self._sigs[sig] = (True, True, True)
++                            signal.signal(num, self.handle)
++                else:
++                    # Make an entry in the _sig dict for these signals
++                    # even though they cannot be ignored or caught.
++                    self._sigs[sig] = (False, False, True)
+ 
+     def info_signal(self, signame):
+         """Print information about a signal"""
+@@ -98,18 +65,14 @@
+             # This has come from pydb's info command
+             if len(signame) == 1:
+                 self.pydb.msg(header)
+-                for sig in self._sig_attr:
+-                    s = sig in self._sig_stop
+-                    pr = sig in self._sig_print
+-                    pa = sig in self._sig_pass
+-                    self.pydb.msg(fmt % (sig,s,pr,pa))
++                for sig in self._sigs.keys():
++                    st, pr, pa = self._sigs[sig]
++                    self.pydb.msg(fmt % (sig, st, pr, pa))
+             else:
+                 self.info_signal(signame[1])
+             return
+             
+-        s = signame in self._sig_stop
+-        pr = signame in self._sig_print
+-        pa = signame in self._sig_pass
++        s, pr, pa = self._sigs[signame]
+         self.pydb.msg(header)
+         self.pydb.msg(fmt % (signame, s, pr, pa))
+ 
+@@ -121,74 +84,83 @@
+             self.info_signal(['handle'])
+             return
+         args = arg.split()
+-        if args[0] in self._sig_attr:
+-            if len(args) == 1:
+-                self.info_signal(args[0])
+-                return
+-            # multiple commands might be specified, i.e. 'nopass nostop'
+-            for attr in args[1:]:
+-                if attr.startswith('no'):
+-                    on = False
+-                    attr = attr[2:]
+-                else:
+-                    on = True
+-                if attr.startswith('stop'):
+-                    self.handle_stop(args[0], on)
+-                elif attr.startswith('print'):
+-                    self.handle_print(args[0], on)
+-                elif attr.startswith('pass'):
+-                    self.handle_pass(args[0], on)
+-                else:
+-                    self.pydb.errmsg('Invalid arguments')
++        try:
++            self._sigs[args[0]]
++        except KeyError:
++            return
++        if len(args) == 1:
++            self.info_signal(args[0])
++            return
++        
++        # We can display information about 'fatal' signals, but not
++        # change their actions.
++        if args[0] in fatal_signals:
++            return
++
++        # multiple commands might be specified, i.e. 'nopass nostop'
++        for attr in args[1:]:
++            if attr.startswith('no'):
++                on = False
++                attr = attr[2:]
++            else:
++                on = True
++            if attr.startswith('stop'):
++                self.handle_stop(args[0], on)
++            elif attr.startswith('print'):
++                self.handle_print(args[0], on)
++            elif attr.startswith('pass'):
++                self.handle_pass(args[0], on)
++            else:
++                self.pydb.errmsg('Invalid arguments')
+ 
+-    def handle_stop(self, signum, change):
++    def handle_stop(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = change, old_attr[1], old_attr[2]
+         if st:
+             pr = True
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+-    def handle_pass(self, signum, change):
++    def handle_pass(self, signame, 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)
++        old_attr = self._sigs[signame]
+         st, pr, pa = old_attr[0], old_attr[1], change
+-        self._set_sig(signum, (st, pr, pa))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     # ignore is a synonym for nopass and noignore is a synonym for pass
+-    def handle_ignore(self, signum, change):
++    def handle_ignore(self, signame, change):
+         if not isinstance(change, bool):
+             return
+         self.handle_pass(not change)
+         return change
+ 
+-    def handle_print(self, signum, change):
++    def handle_print(self, signame, change):
+         """Change whether we print or not when this signal is caught."""
+         if not isinstance(change, bool):
+             return
+-        old_attr = self._get_sig(signum)
++        old_attr = self._sigs[signame]
+         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))
++        self._sigs[signame] = (st, pr, pa)
+         return change
+ 
+     def handle(self, signum, frame):
+         """This method is called when a signal is received."""
+         sig = lookup_signame(signum)
+-        st, pa, pr = self._get_sig(sig)
++        st, pa, pr = self._sigs[sig]
+         if pr:
+             self.pydb.msg('Program received signal %s' % sig)
+         if st:
+Index: test/Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/Makefile.am,v
+retrieving revision 1.17
+diff -u -r1.17 Makefile.am
+--- test/Makefile.am	28 Jul 2006 00:47:47 -0000	1.17
++++ test/Makefile.am	1 Aug 2006 18:08:56 -0000
+@@ -28,6 +28,8 @@
+ 	run.right       \
+ 	run2.cmd        \
+ 	run2.right      \
++	sighandler.cmd  \
++	sighandle.right \
+ 	test.py         \
+ 	trace-2.5.right \
+ 	trace.py        \

Added: sandbox/trunk/pdb/patches/06-08-06-sighandler.cmd
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/06-08-06-sighandler.cmd	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,16 @@
+info signal
+info handle
+handle SIGINT
+handle SIGINT stop pass noprint
+handle SIGINT
+handle SIGINT print
+handle SIGINT
+handle SIGINT nopass noprint nostop
+handle SIGINT
+info signal SIGINT
+# try changing fatal signal handlers (which are unchangable)
+handle SIGKILL stop
+handle SIGKILL
+handle SIGSTOP print
+handle SIGSTOP
+quit

Added: sandbox/trunk/pdb/patches/06-08-06-sighandler.right
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/06-08-06-sighandler.right	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,91 @@
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGWINCH      False	False	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGCONT       True	True	True
+SIGPROF       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         False	False	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGUSR2       True	True	True
+SIGABRT       True	True	True
+SIGALRM       False	False	True
+SIGXFSZ       True	True	True
+SIGCHLD       False	False	True
+SIGPIPE       True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        False	False	True
+SIGPWR        True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+SIGTTIN       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGWINCH      False	False	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGCONT       True	True	True
+SIGPROF       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         False	False	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGUSR2       True	True	True
+SIGABRT       True	True	True
+SIGALRM       False	False	True
+SIGXFSZ       True	True	True
+SIGCHLD       False	False	True
+SIGPIPE       True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        False	False	True
+SIGPWR        True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+SIGTTIN       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False
+Signal        Stop	Print	Pass to program
+
+SIGKILL       False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGSTOP       False	False	True

Added: sandbox/trunk/pdb/patches/10-07-06-opts.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/10-07-06-opts.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,31 @@
+? configure.lineno
+Index: pydb/fns.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/fns.py,v
+retrieving revision 1.11
+diff -u -r1.11 fns.py
+--- pydb/fns.py	4 Jul 2006 06:02:46 -0000	1.11
++++ pydb/fns.py	10 Jul 2006 00:20:59 -0000
+@@ -147,12 +147,12 @@
+     except KeyboardInterrupt:
+         pass
+ 
+-def process_options(pydb, debugger_name, program, pkg_version):
++def process_options(pydb, debugger_name, program, pkg_version, option_list):
+     usage_str="""%s [debugger-options] python-script [script-options...]
+ 
+        Runs the extended python debugger""" % (program)
+ 
+-    optparser = OptionParser(usage=usage_str,
++    optparser = OptionParser(usage=usage_str, option_list=option_list,
+                              version="%%prog version %s" % pkg_version)
+ 
+     optparser.add_option("-X", "--trace", dest="linetrace",
+@@ -254,6 +254,7 @@
+                   opts.errors
+             print sys.exc_info()[0]
+             sys.exit(2)
++    return opts
+ 
+ def search_file(filename, path, cdir):
+     """Return a full pathname for filename if we can find one. path

Added: sandbox/trunk/pdb/patches/11-08-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/11-08-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,196 @@
+? pydb.diff
+? pydb/.gdb.py.in.swp
+? test/sigtest.py.in
+? test/sigtestexample.py
+Index: Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/Makefile.am,v
+retrieving revision 1.33
+diff -u -r1.33 Makefile.am
+--- Makefile.am	1 Aug 2006 14:46:19 -0000	1.33
++++ Makefile.am	11 Aug 2006 15:36:47 -0000
+@@ -66,7 +66,7 @@
+ 	-rm $(top_builddir)/pydb/*.pyc
+ 
+ test: check
+-check: pydb/pydb.py pydb/gdb.py test/test.py test/pm.py
++check: pydb/pydb.py pydb/gdb.py test/test.py test/pm.py test/sigtest.py
+ 
+ # 
+ # For the executable, we make a symbolic link to the python program,
+Index: configure.ac
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/configure.ac,v
+retrieving revision 1.35
+diff -u -r1.35 configure.ac
+--- configure.ac	29 Jul 2006 08:09:31 -0000	1.35
++++ configure.ac	11 Aug 2006 15:36:47 -0000
+@@ -126,6 +126,7 @@
+ AC_CONFIG_FILES([test/except.py],[chmod +x test/except.py])
+ AC_CONFIG_FILES([test/pm.py],[chmod +x test/pm.py])
+ AC_CONFIG_FILES([test/settrace.py],[chmod +x test/settrace.py])
++AC_CONFIG_FILES([test/sigtest.py], [chmod +x test/sigtest.py])
+ AC_CONFIG_FILES([test/test.py],[chmod +x test/test.py])
+ AC_CONFIG_FILES([test/trace.py],[chmod +x test/trace.py])
+ 
+Index: pydb/gdb.py.in
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/gdb.py.in,v
+retrieving revision 1.51
+diff -u -r1.51 gdb.py.in
+--- pydb/gdb.py.in	8 Aug 2006 01:34:05 -0000	1.51
++++ pydb/gdb.py.in	11 Aug 2006 15:36:49 -0000
+@@ -21,7 +21,7 @@
+ from pydbcmd import Cmd
+ from pydbbdb import Bdb
+ 
+-from sighandler import SigHandler
++from sighandler import SigHandler, lookup_signame, lookup_signum
+ 
+ class Restart(Exception):
+     """Causes a debugger to be restarted for the debugged Python program."""
+@@ -41,6 +41,7 @@
+ 
+         # set up signal handling
+         self._sig_handler = SigHandler(self)
++        self._reset_handler = None
+ 
+         self.__init_info()
+         self.__init_set()
+@@ -118,6 +119,23 @@
+         except ImportError:
+             self.histfile = None
+ 
++    def trace_dispatch(self, frame, event, arg):
++        for sig in self._sig_handler._sigs.keys():
++            if self._sig_handler._sigs[sig][0] == True:
++                import signal
++                sig_num = lookup_signum(sig)
++                old_handler = signal.getsignal(sig_num)
++                if old_handler != self._sig_handler.handle:
++                    # save the program's signal handler
++                    self._sig_handler.old_handlers[sig_num] = old_handler
++                    
++                    # restore _our_ signal handler
++                    signal.signal(sig_num, self._sig_handler.handle)
++
++        Bdb.trace_dispatch(self, frame, event, arg)
++        return self.trace_dispatch
++
++
+     def __adjust_frame(self, pos, absolute_pos):
+         """Adjust stack frame by pos positions. If absolute_pos then
+         pos is an absolute number. Otherwise it is a relative number.
+Index: pydb/sighandler.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/sighandler.py,v
+retrieving revision 1.6
+diff -u -r1.6 sighandler.py
+--- pydb/sighandler.py	8 Aug 2006 02:04:25 -0000	1.6
++++ pydb/sighandler.py	11 Aug 2006 15:36:49 -0000
+@@ -7,9 +7,8 @@
+ #  - remove pychecker errors.
+ #  - can remove signal handler altogether when
+ #         ignore=True, print=False, pass=True
+-#  - write real regression tests.
+-#  
+ #     
++#
+ import signal
+ 
+ def lookup_signame(num):
+@@ -44,6 +43,8 @@
+     def __init__(self, pydb): 
+         self.pydb = pydb
+         self._sigs = {}
++    
++        self.old_handlers = {}
+ 
+         # set up signal handling for some known signals
+         ignore= ['SIGALRM', 'SIGCHLD',  'SIGURG',  'SIGIO',      'SIGVTALRM'
+@@ -59,7 +60,8 @@
+                             self._sigs[sig] = (False, False, True)
+                         else:
+                             self._sigs[sig] = (True, True, True)
+-                            signal.signal(num, self.handle)
++                            old_handler = signal.signal(num, self.handle)
++                            self.old_handlers[num] = old_handler
+                 else:
+                     # Make an entry in the _sig dict for these signals
+                     # even though they cannot be ignored or caught.
+@@ -93,9 +95,7 @@
+             self.info_signal(['handle'])
+             return
+         args = arg.split()
+-        try:
+-            self._sigs[args[0]]
+-        except KeyError:
++        if not self._sigs.has_key(args[0]):
+             return
+         if len(args) == 1:
+             self.info_signal(args[0])
+@@ -131,6 +131,7 @@
+         old_attr = self._sigs[signame]
+         st, pr, pa = change, old_attr[1], old_attr[2]
+         if st:
++            # stop keyword implies print
+             pr = True
+         self._sigs[signame] = (st, pr, pa)
+         return change
+@@ -151,7 +152,7 @@
+     def handle_ignore(self, signame, change):
+         if not isinstance(change, bool):
+             return
+-        self.handle_pass(not change)
++        self.handle_pass(signame, not change)
+         return change
+ 
+     def handle_print(self, signame, change):
+@@ -169,10 +170,17 @@
+     def handle(self, signum, frame):
+         """This method is called when a signal is received."""
+         sig = lookup_signame(signum)
+-        st, pa, pr = self._sigs[sig]
++        st, pr, pa = self._sigs[sig]
+         if pr:
+             self.pydb.msg('Program received signal %s' % sig)
+         if st:
+-            # XXX Rocky what's the best way to handle this? 
+             self.pydb.use_rawinput = False
++            self.pydb.step_ignore = 1
+             self.pydb.interaction(self.pydb.curframe, None)
++        if pa:
++            # pass the signal to the program by reinstating the old signal
++            # handler and send the signal to this process again
++            old_handler = self.old_handlers[signum]
++            signal.signal(signum, old_handler)
++            import os
++            os.kill(os.getpid(), signum)
+Index: test/Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/Makefile.am,v
+retrieving revision 1.18
+diff -u -r1.18 Makefile.am
+--- test/Makefile.am	8 Aug 2006 01:34:06 -0000	1.18
++++ test/Makefile.am	11 Aug 2006 15:36:49 -0000
+@@ -28,16 +28,16 @@
+ 	run.right       \
+ 	run2.cmd        \
+ 	run2.right      \
+-	sighandler.cmd  \
+-	sighandle.right \
++    sigtest.py      \
++    sigtestexample.py \
+ 	test.py         \
+ 	trace-2.5.right \
+ 	trace.py        \
+ 	trace.right
+ 
+-TESTS = test.py pm.py trace.py
++TESTS = test.py pm.py trace.py sigtest.py
+ 
+ EXTRA_DIST = $(check_DATA) except.py.in pm.py.in \
+-	settrace.py.in test.py.in trace.py.in
++	settrace.py.in test.py.in trace.py.in sigtest.py.in
+ 
+ test: check

Added: sandbox/trunk/pdb/patches/11-08-06-sigtest.py.in
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/11-08-06-sigtest.py.in	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,101 @@
+#!@PYTHON@ -t
+# $Id$
+"Unit test for Extended Python debugger's signal handling commands "
+import os, time, sys, unittest, signal
+
+top_builddir = "@top_builddir@"
+if top_builddir[-1] != os.path.sep:
+    top_builddir += os.path.sep
+sys.path.insert(0, os.path.join(top_builddir, 'pydb'))
+top_srcdir = "@top_srcdir@"
+if top_srcdir[-1] != os.path.sep:
+    top_srcdir += os.path.sep
+sys.path.insert(0, os.path.join(top_srcdir, 'pydb'))
+
+import pydb                
+
+builddir     = "@builddir@"
+if builddir[-1] != os.path.sep:
+    builddir += os.path.sep
+
+top_builddir = "@top_builddir@"
+if top_builddir[-1] != os.path.sep:
+    top_builddir += os.path.sep
+
+srcdir = "@srcdir@"
+if srcdir[-1] != os.path.sep:
+    srcdir += os.path.sep
+
+pydir        = os.path.join(top_builddir, "pydb")
+pydb_short   = "pydb.py"
+pydb_path    = os.path.join(pydir, pydb_short)
+outfile      = 'sighandler.out'
+program      = 'sigtestexample.py'
+
+class SigTests(unittest.TestCase):
+    def tearDown(self):
+        try:
+            os.unlink(outfile)
+        except OSError:
+            pass
+
+    def create_proc(self, cmds):
+        pid = os.spawnlp(os.P_NOWAIT, pydb_path, pydb_path, '-o',
+                         outfile, '-e', '%s' % cmds, program)
+        time.sleep(1.0)
+        return pid
+
+    def test_pass(self):
+        # Run pydb and turn on passing SIGUSR1 signal to the test programs'
+        # signal handler.  
+        cmds = 'handle SIGUSR1 nostop;;step;;step'
+
+        pid = self.create_proc(cmds)
+
+        os.kill(pid, signal.SIGUSR1)
+        os.waitpid(pid, 0)
+
+
+        f = open('log', 'r')
+        line = f.readline()
+        f.close()
+        self.assertEqual(line, 'signal received\n')
+        os.unlink('log')
+
+        f = open(outfile, 'r')
+        lines = f.readlines()
+        f.close()
+        self.assertFalse('Program received signal' in lines)
+         
+    def test_nopass(self):
+        # Run pydb and intercept the signal SIGUSR1 instead of passing it
+        # to the program.
+        cmds = 'handle SIGUSR1 nopass nostop'
+    
+        pid = self.create_proc(cmds)
+
+        os.kill(pid, signal.SIGUSR1)
+        os.waitpid(pid, 0)
+
+        f = open(outfile, 'r')
+        lines = f.readlines()
+        f.close()
+
+        self.assertEqual(lines[1], 'Program received signal SIGUSR1\n') 
+
+    def test_noprint(self):
+        cmds = "handle SIGUSR1 noprint nopass"
+        pid = self.create_proc(cmds)
+
+        os.kill(pid, signal.SIGUSR1)
+        os.waitpid(pid, 0)
+
+        f = open(outfile, 'r')
+        lines = f.readlines()
+        f.close()
+
+        self.assertFalse('Program received signal SIGUSR1\n' in lines)
+        self.assertRaises(IOError, open, 'log', 'r')
+
+if __name__ == '__main__':
+    unittest.main()

Added: sandbox/trunk/pdb/patches/11-08-06-sigtestexample.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/11-08-06-sigtestexample.py	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,9 @@
+def func(num, f):
+    f = open('log', 'w+')
+    f.write('signal received\n')
+    f.close()
+
+import signal
+signal.signal(signal.SIGUSR1, func)
+
+x = 2

Added: sandbox/trunk/pdb/patches/20-08-06-threaddbg.patch
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/20-08-06-threaddbg.patch	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,306 @@
+--- threaddbg.py	2006/08/07 02:25:13	1.3
++++ threaddbg.py	2006/08/19 20:57:38
+@@ -9,9 +9,23 @@
+ ### - 
+ 
+ import bdb, inspect, os, pydb, sys
+-
++from bdb import Breakpoint, checkfuncname
++from pydb.pydbbdb import checkline
+ import thread, threading
+ 
++class TBreakpoint(Breakpoint):
++
++    """Per-thread Breakpoint class."""
++
++    next = 1
++    bplist = {}
++    bpbynumber = [None]
++
++    def __init__(self, file, line, temporary=0, cond=None, funcname=None,
++                 threadname=None):
++        Breakpoint.__init__(self, file, line, temporary, cond, funcname)
++        self.threadname = threadname
++    
+ class threadDbg(pydb.Pdb):
+ 
+     def __init__(self, completekey='tab', stdin=None, stdout=None):
+@@ -20,6 +34,8 @@
+         self.add_hook()
+         self.stack = self.curframe = self.botframe = None
+ 
++        self.t_breaks = {'MainThread': {}}
++
+         # desired_thread is the thread we want to switch to after issuing
+         # a "thread <thread-name>" command.
+         self.desired_thread=None
+@@ -193,6 +209,7 @@
+         # Record in my own table a list of thread names
+         if not thread_name in self.traced.keys():
+             self.traced[thread_name] = thread.get_ident()
++            self.t_breaks[thread_name] = {}
+ 
+         # See if there was a request to switch to a specific thread
+         while self.desired_thread not in (None,
+@@ -205,11 +222,9 @@
+         self.threading_lock.acquire()
+ 
+         if self.desired_thread != None:
+-            print "Hey we just did a switch to %s!" % self.desired_thread
+             self.threading_cond.acquire()
+             self.threading_cond.notifyAll()
+             self.threading_cond.release()
+-            print "notify done from %s" % threading.currentThread().getName()
+ 
+         self.desired_thread = None
+ 
+@@ -256,3 +271,249 @@
+         statement = 'execfile( "%s")' % filename
+         self.run(statement, globals=globals_, locals=locals_)
+ 
++    def info_breakpoints(self, arg):
++        threadname = threading.currentThread().getName()
++        if not self.breaks and not self.t_breaks[threadname]:
++            self.msg('No breakpoints')
++            return
++
++        have_breaks = False
++        if self.breaks:
++            pydb.Pdb.info_breakpoints(self, arg)
++            have_breaks = True 
++        if self.t_breaks[threadname]:
++            self.msg("\nThread-specific breakpoints:")
++            self.msg("Num Type          Disp Enb    Where                       Thread")
++            for bp in TBreakpoint.bpbynumber:
++                if bp:
++                    self.tbpprint(bp)
++        else:
++            if not have_breaks: self.msg("No breakpoints.")
++
++    info_breakpoints.__doc__ = pydb.Pdb.info_breakpoints.__doc__
++
++    def set_break(self, filename, lineno, temporary=0, cond=None, funcname=None,
++                  threadname=None):
++        if threadname is None:
++            pydb.Pdb.set_break(self, filename, lineno, temporary, cond, funcname)
++        else:
++            filename = self.canonic(filename)
++            import linecache
++            line = linecache.getline(filename, lineno)
++            if not line:
++                return 'Line %s:%d does not exist' % (filename, lineno)
++            
++            if not filename in self.t_breaks:
++                self.t_breaks[threadname][filename] = []
++            blist = self.t_breaks[threadname][filename]
++            if not lineno in blist:
++                blist.append(lineno)
++            bp = TBreakpoint(filename, lineno, temporary, cond, funcname, threadname)
++
++    def do_break(self, arg, temporary=0):
++        if 'thread' not in arg:
++            # We only deal with thread-spefic breakpoints. pydb handles
++            # all others.
++            pydb.Pdb.do_break(self, arg)
++            return
++
++        if not self.curframe:
++            self.msg("No stack.")
++            return
++        # Pull the 'thread' command and threadname out of the args
++        threadname = arg[arg.find('thread')+7:]
++        print threadname.__repr__()
++        arg = arg[:arg.find('thread')-1]
++        cond = None
++        funcname = None
++        if not arg:
++            if self.lineno is None:
++                lineno = max(1, inspect.getlineno(self.curframe))
++            else:
++                lineno = self.lineno + 1
++            filename = self.curframe.f_code.co_filename
++        else:
++            filename = None
++            lineno = None
++            comma = arg.find(',')
++            if comma > 0:  
++                cond = arg[comma+1:].lstrip() 
++                arg = arg[:comma].rstrip()
++            (funcname, filename, lineno) = self.parse_fileops(arg)
++    
++        if not filename:
++            filename = self.defaultFile()
++
++        line = checkline(self, filename, lineno)
++        if line:
++            try:
++                err = self.set_break(filename, line, temporary, cond, funcname, threadname)
++            except TypeError:
++                err = self.set_break(filename, line, temporary, cond, threadname)
++
++            if err: self.errmsg(err)
++            else:
++                bp = self.get_breaks(filename, line, threadname)[-1]
++                self.msg("Breakpoint %d set in file %s, line %d, thread %s."
++                         % (bp.number, self.filename(bp.file), bp.line, bp.threadname))
++
++    do_break.__doc__ = pydb.Pdb.do_break.__doc__
++
++    # XXX This is an _exact_ copy of __parse_fileops from gdb.py
++    # It's only included because of the name mangling
++    def parse_fileops(self, arg):
++        colon = arg.find(':')
++        if colon >= 0:
++            filename = arg[:colon].rstrip()
++            f = self.lookupmodule(filename)
++            if not f:
++                self.errmsg("%s not found on sys.path" %
++                            self.saferepr(filename))
++                return (None, None, None)
++            else:
++                filename = f
++                arg = arg[colon+1:].lstrip()
++            try:
++                lineno = int(arg)
++            except TypeError:
++                self.errmsg("Bad lineno: %s", str(arg))
++                return (None, filename, None)
++            return (None, filename, lineno)
++        else:
++            # no colon: can be lineno or function
++            return self.get_brkpt_lineno(arg)
++
++    # Likewise, this method is only included because of the namespace mangling
++    def get_brkpt_lineno(self, arg):
++        funcname, filename = (None, None)
++        try:
++            lineno = int(arg)
++            filename = self.curframe.f_code.co_filename
++        except ValueError:
++            try:
++                func = eval(arg, self.curframe.f_globals,
++                            self.curframe.f_locals)
++            except:
++                func = arg
++            try:
++                if hasattr(func, 'im_func'):
++                    func = func.im_func
++                code = func.func_code
++                lineno = code.co_firstlineno
++                filename = code.co_filename 
++            except:
++                (ok, filename, ln) = self.lineinfo(arg)
++                if not ok:
++                    self.errmsg(('The specified object %s is not'
++                                +' a fucntion, or not found'
++                                +' along sys.path or not line given.')
++                                % str(repr(arg)))
++                    return (None, None, None)
++                funcname = ok
++                lineno = int(ln)
++        return (funcname, filename, lineno)
++
++    def get_breaks(self, filename, lineno, threadname=None):
++        if threadname is None:
++            return pydb.Pdb.get_breaks(self, filename, lineno)
++        filename = self.canonic(filename)
++        return filename in self.t_breaks[threadname] and \
++            lineno in self.t_breaks[threadname][filename] and \
++            TBreakpoint.bplist[filename, lineno] or []
++
++    def tbpprint(self, bp, out=None):
++        if bp.temporary:      
++            disp = 'del  '    
++        else:
++            disp = 'keep '
++        if bp.enabled:
++            disp = disp + 'y  '            
++        else:
++            disp = disp + 'n  '            
++        self.msg('%-4dbreakpoint    %s at %s:%d in %s' %
++                 (bp.number, disp, self.filename(bp.file), bp.line, bp.threadname), out)
++        if bp.cond:
++            self.msg('\tstop only if %s' % (bp.cond))
++        if bp.ignore:
++            self.msg('\tignore next %d hits' % (bp.ignore), out)
++        if (bp.hits):
++            if (bp.hits > 1): ss = 's'     
++            else: ss = ''
++            self.msg('\tbreakpoint already hit %d time%s' %
++                     (bp.hits, ss), out)             
++
++    def break_here(self, frame):
++        if pydb.Pdb.break_here(self, frame):
++            return True
++
++        threadname = threading.currentThread().getName()
++        filename = self.canonic(frame.f_code.co_filename)
++        if not filename in self.t_breaks[threadname]:
++            return False
++        lineno = frame.f_lineno
++        if not lineno in self.t_breaks[threadname][filename]:
++            # The line itself has no breakpoint, but maybe the line is the
++            # first line of a function with breakpoint set by function name.
++            lineno = frame.f_code.co_firstlineno
++            if not lineno in self.t_breaks[threadname][filename]:
++                return False
++
++        # flag says ok to delete temp. bp
++        (bp, flag) = effective(filename, lineno, frame)
++        if bp:
++            self.currentbp = bp.number
++            if (flag and bp.temporary):
++                self.do_clear(str(bp.number))
++            return True
++        else:
++            return False
++
++def effective(file, line, frame):
++    """Determine which breakpoint for this file:line is to be acted upon.
++
++    Called only if we know there is a bpt at this
++    location.  Returns breakpoint that was triggered and a flag
++    that indicates if it is ok to delete a temporary bp.
++
++    """
++    possibles = TBreakpoint.bplist[file,line]
++    for i in range(0, len(possibles)):
++        b = possibles[i]
++        if b.enabled == 0:
++            continue
++        if not checkfuncname(b, frame):
++            continue
++        # Count every hit when bp is enabled
++        b.hits = b.hits + 1
++        if not b.cond:
++            # If unconditional, and ignoring,
++            # go on to next, else break
++            if b.ignore > 0:
++                b.ignore = b.ignore -1
++                continue
++            else:
++                # breakpoint and marker that's ok
++                # to delete if temporary
++                return (b,1)
++        else:
++            # Conditional bp.
++            # Ignore count applies only to those bpt hits where the
++            # condition evaluates to true.
++            try:
++                val = eval(b.cond, frame.f_globals,
++                    frame.f_locals)
++                if val:
++                    if b.ignore > 0:
++                        b.ignore = b.ignore -1
++                        # continue
++                    else:
++                        return (b,1)
++            except:
++                # if eval fails, most conservative
++                # thing is to stop on breakpoint
++                # regardless of ignore count.
++                # Don't delete temporary,
++                # as another hint to user.
++                return (b,0)
++    return (None, None)
++

Added: sandbox/trunk/pdb/patches/24-07-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/24-07-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,221 @@
+? configure.lineno
+Index: pydb/gdb.py.in
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/gdb.py.in,v
+retrieving revision 1.41
+diff -u -r1.41 gdb.py.in
+--- pydb/gdb.py.in	22 Jul 2006 22:39:18 -0000	1.41
++++ pydb/gdb.py.in	24 Jul 2006 14:36:15 -0000
+@@ -258,7 +258,7 @@
+         self.showcmds.add('args',        self.show_args)
+         self.showcmds.add('basename',    self.show_basename)
+         self.showcmds.add('cmdtrace',    self.show_cmdtrace, 2)
+-        self.showcmds.add('commands',    self.show_commands, 2)
++        self.showcmds.add('commands',    self.show_commands, 2, False)
+         self.showcmds.add('history',     self.show_history)
+         self.showcmds.add('interactive', self.show_interactive)
+         self.showcmds.add('linetrace',   self.show_linetrace, 3)
+@@ -1096,87 +1096,14 @@
+         get info about just that subcommand."""
+ 
+         if not arg:
+-            self.help_info([])
++            for subcommand in self.infocmds.list():
++                self.msg_nocr("%s: " % subcommand)
++                self.do_info(subcommand)
+             return
+ 
+-        arglist = arg.split()
+-        arg = arglist[0]
+-        frame=self.curframe
+-        if "args".startswith(arg):
+-            if not self.curframe:
+-                self.msg("No stack.")
+-                return
+-            self.info_args(None)
+-        elif "break".startswith(arg):
+-            # FIXME: Should split out the "info" part in args
+-            self.do_L(None)
+-        elif 'display'.startswith(arg):
+-            if not self.display.displayAll():
+-                self.msg('There are no auto-display expressions now.')
+-        elif "globals".startswith(arg):
+-            if not frame:
+-                self.msg("No frame selected.")
+-                return
+-            self.msg("\n".join(["%s = %s"
+-                                % (l, pprint.pformat(self.getval(l)))
+-                                for l in frame.f_globals]))
+-        elif "line".startswith(arg) and len(arg) > 1:
+-            #info line identifier
+-            if not frame:
+-                self.msg("No line number information available.")
+-                return
+-            if len(arglist) == 2:
+-                # lineinfo returns (item, file, lineno) or (None,)
+-                answer = self.lineinfo(arglist[1])
+-                if answer[0]:
+-                    item, file, lineno = answer
+-                    if not os.path.isfile(file):
+-                        file = search_file(file, self.search_path,
+-                                           self.main_dirname)
+-                    self.msg('Line %s of "%s" <%s>' %
+-                             (lineno, file, item))
+-                return
+-            #info line
+-            file=self.canonic_filename(frame)
+-            if not os.path.isfile(file):
+-                file = search_file(file, self.search_path, self.main_dirname)
+-
+-            self.msg('Line %d of \"%s\" at instruction %d' % 
+-                     (inspect.getlineno(frame),
+-                      self.filename(self.canonic_filename(frame)),
+-                     self.curframe.f_lasti))
+-        elif "locals".startswith(arg) and len(arg) > 1:
+-            if not frame:
+-                self.msg("No frame selected.")
+-                return
+-            self.msg("\n".join(["%s = %s"
+-                                % (l, pprint.pformat(self.getval(l)))
+-                                for l in frame.f_locals]))
+-        elif 'program'.startswith(arg):
+-            if not frame:
+-                self.msg("The program being debugged is not being run.")
+-                return
+-            if self.is_running():
+-                self.msg('Program stopped.')
+-                if self.currentbp:
+-                    self.msg('It stopped at breakpoint %d.' % self.currentbp)
+-                elif self.stop_reason == 'call':
+-                    self.msg('It stopped at a call.')
+-                elif self.stop_reason == 'exception':
+-                    self.msg('It stopped as a result of an exception.')
+-                elif self.stop_reason == 'return':
+-                    self.msg('It stopped at a return.')
+-                else:
+-                    self.msg("It stopped after stepping, next'ing or initial start.")
+-            return
+-        elif "source".startswith(arg):
+-            if not frame:
+-                self.msg("No current source file.")
+-                return
+-            self.msg('Current Python file is %s' %
+-                     self.filename(self.canonic_filename(frame)))
+         else:
+-            self.undefined_cmd("info", arg)
++            args = arg.split()
++            self.infocmds.do(self, args[0], args)
+ 
+     def info_break(self, arg):
+         """info break
+Index: pydb/pydbcmd.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/pydbcmd.py,v
+retrieving revision 1.23
+diff -u -r1.23 pydbcmd.py
+--- pydb/pydbcmd.py	22 Jul 2006 22:39:18 -0000	1.23
++++ pydb/pydbcmd.py	24 Jul 2006 14:36:15 -0000
+@@ -6,7 +6,7 @@
+ of more oriented towards any gdb-like debugger. Also routines that need to
+ be changed from cmd are here.
+ """
+-import cmd, linecache, os, sys, types
++import cmd, linecache, os, pprint, sys, types
+ from fns import *
+ 
+ # Interaction prompt line will separate file and call info from code
+@@ -274,7 +274,7 @@
+             self.commands_doprompt[self.commands_bnum] = False
+             self.cmdqueue = []
+             return 1
+-        return 
++        return
+ 
+     def info_args(self, arg):
+         """Argument variables of current stack frame"""
+@@ -318,9 +318,9 @@
+         if not self.curframe:
+             self.msg("No line number information available.")
+             return
+-        if len(arglist) == 2:
++        if len(arg) == 2:
+             # lineinfo returns (item, file, lineno) or (None,)
+-            answer = self.lineinfo(arglist[1])
++            answer = self.lineinfo(arg[1])
+             if answer[0]:
+                 item, file, lineno = answer
+                 if not os.path.isfile(file):
+@@ -329,6 +329,14 @@
+                 self.msg('Line %s of "%s" <%s>' %
+                          (lineno, file, item))
+             return
++        file=self.canonic_filename(self.curframe)
++        if not os.path.isfile(file):
++            file = search_file(file, self.search_path, self.main_dirname)
++
++        self.msg('Line %d of \"%s\" at instruction %d' %
++                 (inspect.getlineno(self.curframe),
++                  self.filename(self.canonic_filename(self.curframe)),
++                  self.curframe.f_lasti))
+ 
+     def info_locals(self, arg):
+         """Local variables of current stack frame"""
+@@ -362,7 +370,7 @@
+             self.msg("No current source file.")
+             return
+         self.msg('Current Python file is %s' %
+-                 self.filename(self.canonic_filename(frame)))
++                 self.filename(self.canonic_filename(self.curframe)))
+ 
+     def msg(self, msg, out=None):
+         """Common routine for reporting messages.
+Index: pydb/subcmd.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/subcmd.py,v
+retrieving revision 1.1
+diff -u -r1.1 subcmd.py
+--- pydb/subcmd.py	22 Jul 2006 22:39:18 -0000	1.1
++++ pydb/subcmd.py	24 Jul 2006 14:36:15 -0000
+@@ -24,7 +24,11 @@
+ 
+         entry=self.lookup(subcmd_name)
+         if entry:
+-            obj.msg(entry['doc'])
++            d = entry['doc']
++            # Only print one line of the docstring, stopping at the full-stop.
++            if '.' in d:
++                d = d[:d.find('.')]
++            obj.msg(d)
+             return
+         obj.undefined_cmd("help", subcmd_name)
+ 
+@@ -75,6 +79,10 @@
+ 
+     def list(self):
+         l=self.subcmds.keys()
++        for i in l:
++            # Remove subcmd if we don't want it displayed in the list
++            if not self.subcmds[i]['in_list']:
++                l.pop(l.index(i))
+         l.sort()
+         return l
+ 
+Index: test/cmdparse.right
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/cmdparse.right,v
+retrieving revision 1.19
+diff -u -r1.19 cmdparse.right
+--- test/cmdparse.right	22 Jul 2006 22:39:18 -0000	1.19
++++ test/cmdparse.right	24 Jul 2006 14:36:15 -0000
+@@ -295,10 +295,9 @@
+ show args -- Show argument list to give debugged program on start
+ show basename -- Show if we are to show short of long filenames
+ show cmdtrace -- Show if we are to show debugger commands before running
+-show commands -- Show the history of commands you typed
+ show history -- Generic command for showing command history parameters
+ show interactive -- Show whether we are interactive
+-show linetrace -- Show the line tracing status. Can also add 'delay'
++show linetrace -- Show the line tracing status
+ show listsize -- Show number of source lines the debugger will list by default
+ show logging -- Show logging options
+ show prompt -- Show debugger's prompt

Added: sandbox/trunk/pdb/patches/24-07-06-pydb2.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/24-07-06-pydb2.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,269 @@
+Index: pydb/gdb.py.in
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/gdb.py.in,v
+retrieving revision 1.41
+diff -u -r1.41 gdb.py.in
+--- pydb/gdb.py.in	22 Jul 2006 22:39:18 -0000	1.41
++++ pydb/gdb.py.in	24 Jul 2006 16:53:11 -0000
+@@ -258,7 +258,7 @@
+         self.showcmds.add('args',        self.show_args)
+         self.showcmds.add('basename',    self.show_basename)
+         self.showcmds.add('cmdtrace',    self.show_cmdtrace, 2)
+-        self.showcmds.add('commands',    self.show_commands, 2)
++        self.showcmds.add('commands',    self.show_commands, 2, False)
+         self.showcmds.add('history',     self.show_history)
+         self.showcmds.add('interactive', self.show_interactive)
+         self.showcmds.add('linetrace',   self.show_linetrace, 3)
+@@ -1096,87 +1096,14 @@
+         get info about just that subcommand."""
+ 
+         if not arg:
+-            self.help_info([])
++            for subcommand in self.infocmds.list():
++                self.msg_nocr("%s: " % subcommand)
++                self.do_info(subcommand)
+             return
+ 
+-        arglist = arg.split()
+-        arg = arglist[0]
+-        frame=self.curframe
+-        if "args".startswith(arg):
+-            if not self.curframe:
+-                self.msg("No stack.")
+-                return
+-            self.info_args(None)
+-        elif "break".startswith(arg):
+-            # FIXME: Should split out the "info" part in args
+-            self.do_L(None)
+-        elif 'display'.startswith(arg):
+-            if not self.display.displayAll():
+-                self.msg('There are no auto-display expressions now.')
+-        elif "globals".startswith(arg):
+-            if not frame:
+-                self.msg("No frame selected.")
+-                return
+-            self.msg("\n".join(["%s = %s"
+-                                % (l, pprint.pformat(self.getval(l)))
+-                                for l in frame.f_globals]))
+-        elif "line".startswith(arg) and len(arg) > 1:
+-            #info line identifier
+-            if not frame:
+-                self.msg("No line number information available.")
+-                return
+-            if len(arglist) == 2:
+-                # lineinfo returns (item, file, lineno) or (None,)
+-                answer = self.lineinfo(arglist[1])
+-                if answer[0]:
+-                    item, file, lineno = answer
+-                    if not os.path.isfile(file):
+-                        file = search_file(file, self.search_path,
+-                                           self.main_dirname)
+-                    self.msg('Line %s of "%s" <%s>' %
+-                             (lineno, file, item))
+-                return
+-            #info line
+-            file=self.canonic_filename(frame)
+-            if not os.path.isfile(file):
+-                file = search_file(file, self.search_path, self.main_dirname)
+-
+-            self.msg('Line %d of \"%s\" at instruction %d' % 
+-                     (inspect.getlineno(frame),
+-                      self.filename(self.canonic_filename(frame)),
+-                     self.curframe.f_lasti))
+-        elif "locals".startswith(arg) and len(arg) > 1:
+-            if not frame:
+-                self.msg("No frame selected.")
+-                return
+-            self.msg("\n".join(["%s = %s"
+-                                % (l, pprint.pformat(self.getval(l)))
+-                                for l in frame.f_locals]))
+-        elif 'program'.startswith(arg):
+-            if not frame:
+-                self.msg("The program being debugged is not being run.")
+-                return
+-            if self.is_running():
+-                self.msg('Program stopped.')
+-                if self.currentbp:
+-                    self.msg('It stopped at breakpoint %d.' % self.currentbp)
+-                elif self.stop_reason == 'call':
+-                    self.msg('It stopped at a call.')
+-                elif self.stop_reason == 'exception':
+-                    self.msg('It stopped as a result of an exception.')
+-                elif self.stop_reason == 'return':
+-                    self.msg('It stopped at a return.')
+-                else:
+-                    self.msg("It stopped after stepping, next'ing or initial start.")
+-            return
+-        elif "source".startswith(arg):
+-            if not frame:
+-                self.msg("No current source file.")
+-                return
+-            self.msg('Current Python file is %s' %
+-                     self.filename(self.canonic_filename(frame)))
+         else:
+-            self.undefined_cmd("info", arg)
++            args = arg.split()
++            self.infocmds.do(self, args[0], args)
+ 
+     def info_break(self, arg):
+         """info break
+@@ -1468,8 +1395,10 @@
+ 
+         if not arg:
+             for subcommand in self.showcmds.list():
+-                self.msg_nocr("%s: " % subcommand)
+-                self.do_show(subcommand)
++                # Only display commands that are 'in_list'
++                if self.showcmds.subcmds[subcommand]['in_list']:
++                    self.msg_nocr("%s: " % subcommand)
++                    self.do_show(subcommand)
+             return
+ 
+         if self._re_linetrace_delay.match(arg):
+Index: pydb/pydbcmd.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/pydbcmd.py,v
+retrieving revision 1.23
+diff -u -r1.23 pydbcmd.py
+--- pydb/pydbcmd.py	22 Jul 2006 22:39:18 -0000	1.23
++++ pydb/pydbcmd.py	24 Jul 2006 16:53:11 -0000
+@@ -6,7 +6,7 @@
+ of more oriented towards any gdb-like debugger. Also routines that need to
+ be changed from cmd are here.
+ """
+-import cmd, linecache, os, sys, types
++import cmd, linecache, os, pprint, sys, types
+ from fns import *
+ 
+ # Interaction prompt line will separate file and call info from code
+@@ -104,6 +104,10 @@
+                 try:
+                     doc=getattr(self, 'do_' + first_arg).__doc__
+                     if doc:
++                        # We only print the first line, removing any periods
++                        # if they are the last character on the line
++                        doc = doc[:doc.find('\n')]
++                        if doc[-1] == '.': doc = doc[:-1]
+                         self.msg("%s\n" % str(doc))
+                         return
+                 except AttributeError:
+@@ -274,7 +278,7 @@
+             self.commands_doprompt[self.commands_bnum] = False
+             self.cmdqueue = []
+             return 1
+-        return 
++        return
+ 
+     def info_args(self, arg):
+         """Argument variables of current stack frame"""
+@@ -318,9 +322,9 @@
+         if not self.curframe:
+             self.msg("No line number information available.")
+             return
+-        if len(arglist) == 2:
++        if len(arg) == 2:
+             # lineinfo returns (item, file, lineno) or (None,)
+-            answer = self.lineinfo(arglist[1])
++            answer = self.lineinfo(arg[1])
+             if answer[0]:
+                 item, file, lineno = answer
+                 if not os.path.isfile(file):
+@@ -329,6 +333,14 @@
+                 self.msg('Line %s of "%s" <%s>' %
+                          (lineno, file, item))
+             return
++        file=self.canonic_filename(self.curframe)
++        if not os.path.isfile(file):
++            file = search_file(file, self.search_path, self.main_dirname)
++
++        self.msg('Line %d of \"%s\" at instruction %d' %
++                 (inspect.getlineno(self.curframe),
++                  self.filename(self.canonic_filename(self.curframe)),
++                  self.curframe.f_lasti))
+ 
+     def info_locals(self, arg):
+         """Local variables of current stack frame"""
+@@ -362,7 +374,7 @@
+             self.msg("No current source file.")
+             return
+         self.msg('Current Python file is %s' %
+-                 self.filename(self.canonic_filename(frame)))
++                 self.filename(self.canonic_filename(self.curframe)))
+ 
+     def msg(self, msg, out=None):
+         """Common routine for reporting messages.
+Index: pydb/subcmd.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/subcmd.py,v
+retrieving revision 1.1
+diff -u -r1.1 subcmd.py
+--- pydb/subcmd.py	22 Jul 2006 22:39:18 -0000	1.1
++++ pydb/subcmd.py	24 Jul 2006 16:53:12 -0000
+@@ -17,14 +17,21 @@
+                 return self.subcmds[subcmd_name]
+         return None
+ 
+-    def _subcmd_helper(self, subcmd_name, obj, label=False):
++    def _subcmd_helper(self, subcmd_name, obj, label=False, strip=False):
+         """Show help for a single subcommand"""
+         if label:
+             obj.msg_nocr("%s %s --" % (self.name, subcmd_name))
+ 
+         entry=self.lookup(subcmd_name)
+         if entry:
+-            obj.msg(entry['doc'])
++            d = entry['doc']
++            if strip:
++                # Limit the help message to one line (delimited by '\n')
++                if '\n' in d:
++                    d = d[:d.find('\n')]
++                # If the last character is a period, remove it.
++                if d[-1] == '.': d = d[:d.find('.')]
++            obj.msg(d)
+             return
+         obj.undefined_cmd("help", subcmd_name)
+ 
+@@ -54,7 +61,7 @@
+ 
+     # Note: format of help is compatible with ddd.
+     def help(self, obj, *args):
+-        """help for subcommands"""
++        """help for subcommands."""
+ 
+         subcmd_prefix=args[0]
+         if not subcmd_prefix or len(subcmd_prefix) == 0:
+@@ -63,7 +70,7 @@
+ List of %s subcommands:
+ """ % (self.name))
+             for subcmd_name in self.list():
+-                self._subcmd_helper(subcmd_name, obj, True)
++                self._subcmd_helper(subcmd_name, obj, True, True)
+             return
+ 
+         entry=self.lookup(subcmd_prefix)
+@@ -75,6 +82,10 @@
+ 
+     def list(self):
+         l=self.subcmds.keys()
++        for i in l:
++            # Remove subcmd if we don't want it displayed in the list
++            if not self.subcmds[i]['in_list']:
++                l.pop(l.index(i))
+         l.sort()
+         return l
+ 
+Index: test/cmdparse.right
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/cmdparse.right,v
+retrieving revision 1.19
+diff -u -r1.19 cmdparse.right
+--- test/cmdparse.right	22 Jul 2006 22:39:18 -0000	1.19
++++ test/cmdparse.right	24 Jul 2006 16:53:12 -0000
+@@ -295,7 +295,6 @@
+ show args -- Show argument list to give debugged program on start
+ show basename -- Show if we are to show short of long filenames
+ show cmdtrace -- Show if we are to show debugger commands before running
+-show commands -- Show the history of commands you typed
+ show history -- Generic command for showing command history parameters
+ show interactive -- Show whether we are interactive
+ show linetrace -- Show the line tracing status. Can also add 'delay'

Added: sandbox/trunk/pdb/patches/27-07-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/27-07-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,27 @@
+Index: pydb/fns.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/fns.py,v
+retrieving revision 1.17
+diff -u -r1.17 fns.py
+--- pydb/fns.py	13 Jul 2006 07:45:09 -0000	1.17
++++ pydb/fns.py	27 Jul 2006 17:48:29 -0000
+@@ -256,6 +256,9 @@
+                          action="store", type='string',
+                          help="Write debugger's error output "
+                          + "(stderr) to FILE")
++    optparser.add_option("-e", "--exec", dest="execute", type="string",
++                        help="A comma-separate list of commands to " +
++                        "execute.")
+ 
+     # Set up to stop on the first non-option because that's the name
+     # of the script to be debugged on arguments following that are
+@@ -297,6 +300,9 @@
+     if opts.command:
+         pydb.setup_source(os.path.expanduser(opts.command), True);
+ 
++    if opts.execute:
++        pydb.cmdqueue = list(opts.execute.split(','))
++
+     if opts.output:
+         try: 
+             pydb.stdout = open(opts.output, 'w')

Added: sandbox/trunk/pdb/patches/27-07-06-sighandler.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/27-07-06-sighandler.py	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,112 @@
+"""$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
+            
+    

Added: sandbox/trunk/pdb/patches/30-05-06-pdb.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/30-05-06-pdb.py	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,116 @@
+# Use the version of Pdb that's in svn trunk because the constructor
+# from Pdb needs to take a stdin and stdout argument.
+class MPdb(pdb.Pdb):
+    def __init__(self, sys.stdin, sys.stdout):
+        """ Use sys.stdin and sys.stdout for our input
+        and output streams respectively.
+        """
+
+    def do_list(self, args):
+        """ Override pdb's implementation of the list command """"
+
+    def do_info(self, args):
+        """ Provide information about [args] like the gdb info
+        command.
+        """
+
+    def do_thread(self, thread_no):
+        """ Use this command to switch between threads or to apply
+        a command to all threads.
+        """
+
+    def do_attach(self, location):
+        """ fork a new MXXXConsole object and close this one. """
+
+class MSocketConsole(MPdb):
+    """ A debugging console that connects to a debugging
+    server on a socket. We leave stdin and stdout in tact
+    """
+    def __init__(self, stdin, stdout)
+    
+    def do_attach(self, args):
+        """ Attach to a debugging server. """
+
+    def write(self, cmd):
+        """ Send a command to the debugging server. """
+
+    def read(self):
+        """ Receive output from a debugging server. """
+
+    def cmdloop(self):
+        """ Loop until we exit sending and receiving commands
+        and output from the debugging server.
+        """
+
+# SERVER CLASSES
+
+# What I'm think would be cool here is allowing a design where a
+# programmer can combine MPdb and a server class to produce a working
+# debugging server. Below are some samples
+
+# It is possible for someone to write a wrapper for this class to allow
+# XMLRPC communication over SSL. See, 
+# http://www.shipyard.com.au/articles/webdevelopment/sslxmlrpc.py
+class MXMLRPCServer(MPdb, SimpleXMLRPCServer):
+    def __init__(self, stdin, stdout, host, port):
+        """ A XMLRPC server. """
+
+    def _register_functions(Self):
+        """ Register all MPdb functions with the XMLRPC
+        server.
+        """
+
+    def do_list(self, args):
+        """ This is an example of a method that one may wish to override
+        in order to provide the debugging console (which may end up being
+        a GUI front-end) with more structured information than that which
+        is available in the inherited methods.
+
+        For example, one may wish to return the contents of an entire file
+        for the GUIs parsing plus a tag indicating where we currently
+        are in the file.
+        """
+
+# It is possible to provide a wrapper class for this to enable SSL
+# See above for more info (url link above MXMLRPCServer class)
+class MTCPSocketServer(MPdb, SocketServer.TCPServer):
+    def __init__(self, stdin, stdout, host, port):
+        """ A socket server implementation of a debugging
+        server.
+        """
+
+    def handle_request(self):
+        """ Override the method from TCPServer.
+        Handle requests coming in on the socket.
+
+        Most of the work of this entire class will be done in
+        this method. For instance,
+
+        - redirecting self.stdin and self.stdout to the connected
+        sockets
+        - providing any authentication methods
+        """
+
+class MSerialServer(MPdb):
+    """ A class that sets up a debugging server for use with serial
+    communication, such as that through a serial port.
+    """
+    def __init__(self, stdin, stdout, device):
+        """ Specify the serial device on the computer as a file from
+        /dev to read and write serial information from and to.
+        """
+
+    def listen(self):
+        """ Listen on the serial device for connecting debugging
+        consoles.
+        """
+
+    def accept(self):
+        """ Accept a debugging console connection through the serial
+        device.
+        """
+
+
+    
+    
+    

Added: sandbox/trunk/pdb/patches/31-07-06-fns.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-fns.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,26 @@
+Index: pydb/fns.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/fns.py,v
+retrieving revision 1.15
+diff -u -r1.15 fns.py
+--- pydb/fns.py	10 Jul 2006 07:21:32 -0000	1.15
++++ pydb/fns.py	11 Jul 2006 20:41:11 -0000
+@@ -55,12 +55,12 @@
+         except EOFError:
+             reply = 'no'
+             reply = reply.strip().lower()
+-            if reply in ('y', 'yes'):
+-                return True
+-            elif reply in ('n', 'no'):
+-                return False
+-            else:
+-                self.msg("Please answer y or n.")
++        if reply in ('y', 'yes'):
++            return True
++        elif reply in ('n', 'no'):
++            return False
++        else:
++            self.msg("Please answer y or n.")
+     return False
+                 
+ 

Added: sandbox/trunk/pdb/patches/31-07-06-pydb.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-pydb.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,33 @@
+Index: pydb/sighandler.py
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/sighandler.py,v
+retrieving revision 1.3
+diff -u -r1.3 sighandler.py
+--- pydb/sighandler.py	31 Jul 2006 00:14:54 -0000	1.3
++++ pydb/sighandler.py	31 Jul 2006 10:02:20 -0000
+@@ -32,9 +32,6 @@
+     """
+     def __init__(self, pydb): 
+         self.pydb = pydb
+-        # This list contains tuples made up of four items, one tuple for
+-        # every signal handler we've created. The tuples contain
+-        # (signal_num, stop, print, pass)
+         self._sig_attr = []
+         self._sig_stop = []
+         self._sig_print = []
+Index: test/Makefile.am
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/test/Makefile.am,v
+retrieving revision 1.17
+diff -u -r1.17 Makefile.am
+--- test/Makefile.am	28 Jul 2006 00:47:47 -0000	1.17
++++ test/Makefile.am	31 Jul 2006 10:02:20 -0000
+@@ -28,6 +28,8 @@
+ 	run.right       \
+ 	run2.cmd        \
+ 	run2.right      \
++	sighandler.cmd  \
++	sighandle.right \
+ 	test.py         \
+ 	trace-2.5.right \
+ 	trace.py        \

Added: sandbox/trunk/pdb/patches/31-07-06-sig.diff
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-sig.diff	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,66 @@
+? sig.diff
+? t.py
+? thread_script2.py
+? tpdb.py
+? tpdb2.py
+? pydb/.gdb.py.in.swp
+? pydb/sighandler.py
+Index: pydb/gdb.py.in
+===================================================================
+RCS file: /cvsroot/bashdb/pydb/pydb/gdb.py.in,v
+retrieving revision 1.49
+diff -u -r1.49 gdb.py.in
+--- pydb/gdb.py.in	29 Jul 2006 08:09:32 -0000	1.49
++++ pydb/gdb.py.in	30 Jul 2006 23:17:40 -0000
+@@ -21,6 +21,8 @@
+ from pydbcmd import Cmd
+ from pydbbdb import Bdb
+ 
++from sighandler import SigHandler
++
+ class Restart(Exception):
+     """Causes a debugger to be restarted for the debugged Python program."""
+     pass
+@@ -37,6 +39,9 @@
+         self._re_linetrace_delay  = re.compile(r'\s*linetrace\s+delay')
+         self._wait_for_mainpyfile = False
+ 
++        # set up signal handling
++        self._sig_handler = SigHandler(self)
++
+         self.__init_info()
+         self.__init_set()
+         self.__init_show()
+@@ -236,10 +241,12 @@
+         self.infocmds.add('args',         self.info_args)
+         self.infocmds.add('breakpoints',  self.info_breakpoints)
+         self.infocmds.add('display',      self.info_display)
++        self.infocmds.add('handle',       self._sig_handler.info_signal)
+         self.infocmds.add('globals',      self.info_globals, 1, False)
+         self.infocmds.add('line',         self.info_line)
+         self.infocmds.add('locals',       self.info_locals,  1, False)
+         self.infocmds.add('program',      self.info_program)
++        self.infocmds.add('signal',       self._sig_handler.info_signal)
+         self.infocmds.add('source',       self.info_source)
+ 
+     def __init_set(self):
+@@ -1043,6 +1050,19 @@
+         else:
+             self.__adjust_frame(pos=arg, absolute_pos=True)
+ 
++    def do_handle(self, arg):
++        """Specify how to handle a signal.
++        Args are signals and actions to apply to those signals.
++        Recognized actions include "stop", "nostop", "print", "noprint",
++        "pass", "nopass", "ignore", or "noignore".
++        Stop means reenter debugger if this signal happens (implies print).
++        Print means print a message if this signal happens.
++        Pass means let program see this signal; otherwise program doesn't know.
++        Ignore is a synonym for nopass and noignore is a synonym for pass.
++        Pass and Stop may be combined.
++        """
++        self._sig_handler.action(arg)
++
+     def do_ignore(self,arg):
+         """ignore bpnumber count
+ 

Added: sandbox/trunk/pdb/patches/31-07-06-sighandler.cmd
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-sighandler.cmd	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,11 @@
+info signal
+info handle
+handle SIGINT
+handle SIGINT stop pass noprint
+handle SIGINT
+handle SIGINT print
+handle SIGINT
+handle SIGINT nopass noprint nostop
+handle SIGINT
+info signal SIGINT
+quit

Added: sandbox/trunk/pdb/patches/31-07-06-sighandler.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-sighandler.py	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,190 @@
+"""$Id $
+Handles signal handlers within Pydb.
+"""
+import signal
+
+def lookup_signame(num):
+    """Find the corresponding signal name for 'num'. Return None
+    if 'num' is invalid."""
+    for signame in signal.__dict__.keys():
+        if signal.__dict__[signame] == num:
+            return signame
+
+def lookup_signum(name):
+    """Find the corresponding signal number for 'name'. Return None
+    if 'name' is invalid."""
+    if hasattr(signal, name):
+        return getattr(signal, name)
+    else:
+        return None
+
+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, pydb): 
+        self.pydb = pydb
+        # This list contains tuples made up of four items, one tuple for
+        # every signal handler we've created. The tuples contain
+        # (signal_num, stop, print, pass)
+        self._sig_attr = []
+        self._sig_stop = []
+        self._sig_print = []
+        self._sig_pass = []
+
+        for sig in signal.__dict__.keys():
+            if sig.startswith('SIG') and '_' not in sig:
+                self._sig_attr.append(sig)
+
+        # set up signal handling for some known signals
+        fatal = ['SIGINT', 'SIGTRAP', 'SIGTERM', 'SIGQUIT', 'SIGILL', \
+                 'SIGKILL', 'SIGSTOP']
+        for sig in self._sig_attr:
+            if str(sig) not in fatal:
+                num = lookup_signum(sig)
+                if num:
+                    self._set_sig(sig, (True, True, True))
+                    signal.signal(num, self.handle)
+            else:
+                self._set_sig(sig, (False, False, True))
+
+    def _get_sig(self, name):
+        st = name in self._sig_stop
+        pr = name in self._sig_print
+        pa = name in self._sig_pass
+        return (st, pr, pa)
+
+    def _set_sig(self, name, (st, pr, pa)):
+        """Set the actions to be taken when a signal, specified by
+        'name', is received.
+        """
+        if st:
+            if name not in self._sig_stop:
+                self._sig_stop.append(name)
+        else:
+            if name in self._sig_stop:
+                self._sig_stop.pop(self._sig_stop.index(name))
+        if pr:
+            if name not in self._sig_print:
+                self._sig_print.append(name)
+        else:
+            if name in self._sig_print:
+                self._sig_print.pop(self._sig_print.index(name))
+        if pa:
+            if name not in self._sig_pass:
+                self._sig_pass.append(name)
+        else:
+            if name in self._sig_pass:
+                self._sig_pass.pop(self._sig_pass.index(name))
+
+    def info_signal(self, signame):
+        """Print information about a signal"""
+        if 'handle' in signame or 'signal' in signame:
+            # This has come from pydb's info command
+            if len(signame) == 1:
+                self.pydb.msg('NAME\t\tSTOP\tPRINT\tPASS')
+                for sig in self._sig_attr:
+                    s = sig in self._sig_stop
+                    pr = sig in self._sig_print
+                    pa = sig in self._sig_pass
+                    self.pydb.msg('%s\t\t%s\t%s\t%s' % (sig,s,pr,pa))
+            else:
+                self.info_signal(signame[1])
+            return
+            
+        s = signame in self._sig_stop
+        pr = signame in self._sig_print
+        pa = signame in self._sig_pass
+        self.pydb.msg('NAME\t\tSTOP\tPRINT\tPASS')
+        self.pydb.msg('%s\t\t%s\t%s\t%s' % (signame, s, pr, pa))
+
+    def action(self, arg):
+        """Delegate the actions specified in 'arg' to another
+        method.
+        """
+        if not arg:
+            self.info_signal(['handle'])
+            return
+        args = arg.split()
+        if args[0] in self._sig_attr:
+            if len(args) == 1:
+                self.info_signal(args[0])
+                return
+            # multiple commands might be specified, i.e. 'nopass nostop'
+            for attr in args[1:]:
+                if attr.startswith('no'):
+                    on = False
+                    attr = attr[2:]
+                else:
+                    on = True
+                if attr.startswith('stop'):
+                    self.handle_stop(args[0], on)
+                elif attr.startswith('print'):
+                    self.handle_print(args[0], on)
+                elif attr.startswith('pass'):
+                    self.handle_pass(args[0], on)
+                else:
+                    self.pydb.errmsg('Invalid arguments')
+
+    def handle_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 handle_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 handle_ignore(self, signum, change):
+        if not isinstance(change, bool):
+            return
+        self.handle_pass(not change)
+        return change
+
+    def handle_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."""
+        sig = lookup_signame(signum)
+        st, pa, pr = self._get_sig(sig)
+        if pr:
+            self.pydb.msg('Program received signal %s' % sig)
+        if st:
+            # XXX Rocky what's the best way to handle this? 
+            self.pydb.use_rawinput = False
+            self.pydb.interaction(self.pydb.curframe, None)

Added: sandbox/trunk/pdb/patches/31-07-06-sighandler.right
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-sighandler.right	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,85 @@
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGCHLD       True	True	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGPROF       True	True	True
+SIGCONT       True	True	True
+SIGUSR2       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         True	True	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGABRT       True	True	True
+SIGALRM       True	True	True
+SIGPIPE       True	True	True
+SIGWINCH      True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        True	True	True
+SIGPWR        True	True	True
+SIGXFSZ       True	True	True
+SIGTTIN       True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGHUP        True	True	True
+SIGSYS        True	True	True
+SIGQUIT       False	False	True
+SIGUSR1       True	True	True
+SIGFPE        True	True	True
+SIGTSTP       True	True	True
+SIGCHLD       True	True	True
+SIGIOT        True	True	True
+SIGBUS        True	True	True
+SIGXCPU       True	True	True
+SIGPROF       True	True	True
+SIGCONT       True	True	True
+SIGUSR2       True	True	True
+SIGKILL       False	False	True
+SIGSEGV       True	True	True
+SIGINT        False	False	True
+SIGIO         True	True	True
+SIGTRAP       False	False	True
+SIGILL        False	False	True
+SIGEMT        True	True	True
+SIGABRT       True	True	True
+SIGALRM       True	True	True
+SIGPIPE       True	True	True
+SIGWINCH      True	True	True
+SIGTERM       False	False	True
+SIGVTALRM     True	True	True
+SIGINFO       True	True	True
+SIGURG        True	True	True
+SIGPWR        True	True	True
+SIGXFSZ       True	True	True
+SIGTTIN       True	True	True
+SIGSTOP       False	False	True
+SIGTTOU       True	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	True	True
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False
+Signal        Stop	Print	Pass to program
+
+SIGINT        False	False	False

Added: sandbox/trunk/pdb/patches/31-07-06-test.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/patches/31-07-06-test.py	Mon Aug 21 17:49:31 2006
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+"""Run a bunch of threading programs with line tracing
+to make sure we don't hang tracing them."""
+
+import os, time
+
+def run_test(test, wait_period):
+    """Run the test 'test' in a separate process and sleep for 'wait_period'
+    seconds. 'wait_period' should specify an optimal amount of time for
+    'test' to finish. If the process hasn't finished by the time 
+    'wait_period' seconds have passed, we assume that the test is hung.
+    If the test has hung False is returned, otherwise True is returned.
+    """
+    pid = os.spawnlp(os.P_NOWAIT, 'python', 'python', 'tpdb.py', '--trace',
+                    test)
+    time.sleep(wait_period)
+    ret = os.waitpid(pid, os.WNOHANG)
+    if ret == (0,0):
+        import signal
+        os.kill(pid, signal.SIGKILL)
+        return False
+    else:
+        return True
+    
+def main():
+    # The way that I got the times  below was by timing each file on
+    # my AMD64 machine and adding 5 seconds on to it. We may find that
+    # these times are way too short.
+    tests = [('t2.py', 5.0), ('q.py', 15.0), ('thread1.py',10.0)]
+    failed_tests = []
+
+    # Construct a test command suitable for passing to run_test
+    for test in tests:
+        filename = os.path.realpath(test[0])
+        result = run_test(filename, test[1])
+        if not result:
+            failed_tests.append(test)
+        
+    if failed_tests:
+        print '=' * 60
+        print 'Failed Tests:\n'
+        for failed in failed_tests:
+            print failed[0]
+        print '=' * 60
+    else:
+        print '=' * 60
+        print 'All tests passed\n'
+        print '=' * 60
+        
+if __name__ == '__main__':
+    main()


More information about the Python-checkins mailing list