short-circuiting runtime errors/exceptions in python debugger.

all, I was debugging a very long script that I was not all that familiar with, and I was doing my familiar routine of being very careful in evaluating expressions to make sure that I didn't hit such statements as: TypeError: unsupported operand type(s) for +: 'int' and 'str' anyways the script has a runtime of hours, so this was tedious work, and I hit one-too-many times where I missed a condition and had to start all over again. So that got me thinking: the main problem with exceptions and runtime errors is that they short-circuit the program context. You have this context, but you can't change it to avoid the failure; ie: with 1. aa = 'a' 2. bb = 1 + a 3. print bb you'll never get to line 3 if you go through line 2. If you are lucky you can catch it, modify aa to be an integer to continue, otherwise your only recourse is to start over again. So I was wondering if it would be possible to keep that context around if you are in the debugger and rewind the execution point to before the statement was triggered. so you could say: python script.py (Pdb) c then hit the exception, say: (Pdb) aa = 2 then run again (Pdb) c to work your way through the exception point. You could then fix the script inline in an editor. I can't emphasize exactly how much time and effort this would save. At best, debugging these types of issues is annoying, at worst it is excruciating, because they are sometimes intermittent and are not easily repeatable. Using RemotePdb or Pdb to attach to a long-running process and having the assurance that the underlying script won't die because of an inane coding error would do wonders for the reliability and integrity of scripting. so - is this possible? just from my experiments it doesn't look so, but perhaps there is a trick out there that would give this functionality.. if it isn't possible, how easy would it be to implement? Thanks much, Ed

On Fri, Oct 26, 2018 at 04:18:37PM -0700, Ed Peschko wrote:
all,
I was debugging a very long script that I was not all that familiar with, and I was doing my familiar routine of being very careful in evaluating expressions to make sure that I didn't hit such statements as:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
anyways the script has a runtime of hours, so this was tedious work, and I hit one-too-many times where I missed a condition and had to start all over again.
Obviously you weren't careful enough :-) You know you can set breakpoints in the debugger? You don't have to single-step all the way through from the beginning. It isn't clear from your post how experienced you are. [...]
So I was wondering if it would be possible to keep that context around if you are in the debugger and rewind the execution point to before the statement was triggered.
I think what you are looking for is a reverse debugger[1] also known as a time-travel debugger. https://softwareengineering.stackexchange.com/questions/181527/why-is-revers... There's a Python implementation, but I've never used it: https://morepypy.blogspot.com/2016/07/reverse-debugging-for-python.html [...]
I can't emphasize exactly how much time and effort this would save.
That's what people say. But not everyone is a fan -- there are apparently memory consumption and stability issues with reverse debugging. There are people who love it, and those who don't.
so - is this possible? just from my experiments it doesn't look so, but perhaps there is a trick out there that would give this functionality..
if it isn't possible, how easy would it be to implement?
If it isn't possible, it would be very difficult to implement :-) [1] A reverse debugger is not the process of adding bugs to code *wink* -- Steve

Hi, On Sat, 27 Oct 2018 at 01:50, Steven D'Aprano <steve@pearwood.info> wrote:
[...]
So I was wondering if it would be possible to keep that context around if you are in the debugger and rewind the execution point to before the statement was triggered.
I think what you are looking for is a reverse debugger[1] also known as a time-travel debugger.
I think it's a bit different. A reverse debugger is here to debug complex conditions in a (static) program. What Ed is looking for is a way to catch easy failures, fix the obviously faulty line, and continue running the program. Of course I can't help but mention to Ed that this is precisely the kind of easy failures that are found by *testing* your code, particularly if that's code that only runs after hours of other code has executed. *Never* trust yourself to write correct code if you don't know that it is correct after waiting for hours. But assuming that you really, really are allergic to tests, then what you're looking for reminds me of long-ago Python experiments with resumable exceptions and patching code at runtime. Both topics are abandoned now. Resumable exceptions was a cool hack of the interpreter that nobody really found a use for (AFAIR); patching code at runtime comes with a pile of messes---it only works in the simple cases, but there is no general solution for that. A bientôt, Armin.

A simpler feature that could possibly help him (assuming there isn't any external state to deal with) would be the ability to save everything at a certain point in time, and then resume it later. He could rig things up to save the state e.g. after every hour: 1 hour, 2 hours, etc. Then if an error occurs after 2.5 hours, he could at least start resuming after 2 hours. This could be viewed as a cheap form of a reverse debugger, because a reverse debugger has to save the state at every point in time, not just at a few select points. --Chris On Mon, Oct 29, 2018 at 9:51 AM Armin Rigo <armin.rigo@gmail.com> wrote:
Hi,
On Sat, 27 Oct 2018 at 01:50, Steven D'Aprano <steve@pearwood.info> wrote:
[...]
So I was wondering if it would be possible to keep that context around if you are in the debugger and rewind the execution point to before the statement was triggered.
I think what you are looking for is a reverse debugger[1] also known as a time-travel debugger.
I think it's a bit different. A reverse debugger is here to debug complex conditions in a (static) program. What Ed is looking for is a way to catch easy failures, fix the obviously faulty line, and continue running the program.
Of course I can't help but mention to Ed that this is precisely the kind of easy failures that are found by *testing* your code, particularly if that's code that only runs after hours of other code has executed. *Never* trust yourself to write correct code if you don't know that it is correct after waiting for hours.
But assuming that you really, really are allergic to tests, then what you're looking for reminds me of long-ago Python experiments with resumable exceptions and patching code at runtime. Both topics are abandoned now. Resumable exceptions was a cool hack of the interpreter that nobody really found a use for (AFAIR); patching code at runtime comes with a pile of messes---it only works in the simple cases, but there is no general solution for that.
A bientôt,
Armin. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/chris.jerdonek%40gmail.co...

I have another idea on this. What about the idea of starting the program, and then a few minutes later, starting the same program a second time. If the first program errors, you could examine the second one which is a little bit behind. Before starting the second one, perhaps you could even make a copy of the second one and pause it for a few minutes before restarting, in case the second one also errors out, and so on. This would be more useful only in the case of deterministic errors. --Chris On Mon, Oct 29, 2018 at 11:59 AM Chris Jerdonek <chris.jerdonek@gmail.com> wrote:
A simpler feature that could possibly help him (assuming there isn't any external state to deal with) would be the ability to save everything at a certain point in time, and then resume it later. He could rig things up to save the state e.g. after every hour: 1 hour, 2 hours, etc. Then if an error occurs after 2.5 hours, he could at least start resuming after 2 hours. This could be viewed as a cheap form of a reverse debugger, because a reverse debugger has to save the state at every point in time, not just at a few select points.
--Chris
On Mon, Oct 29, 2018 at 9:51 AM Armin Rigo <armin.rigo@gmail.com> wrote:
Hi,
On Sat, 27 Oct 2018 at 01:50, Steven D'Aprano <steve@pearwood.info> wrote:
[...]
So I was wondering if it would be possible to keep that context around if you are in the debugger and rewind the execution point to before the statement was triggered.
I think what you are looking for is a reverse debugger[1] also known as a time-travel debugger.
I think it's a bit different. A reverse debugger is here to debug complex conditions in a (static) program. What Ed is looking for is a way to catch easy failures, fix the obviously faulty line, and continue running the program.
Of course I can't help but mention to Ed that this is precisely the kind of easy failures that are found by *testing* your code, particularly if that's code that only runs after hours of other code has executed. *Never* trust yourself to write correct code if you don't know that it is correct after waiting for hours.
But assuming that you really, really are allergic to tests, then what you're looking for reminds me of long-ago Python experiments with resumable exceptions and patching code at runtime. Both topics are abandoned now. Resumable exceptions was a cool hack of the interpreter that nobody really found a use for (AFAIR); patching code at runtime comes with a pile of messes---it only works in the simple cases, but there is no general solution for that.
A bientôt,
Armin. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/chris.jerdonek%40gmail.co...

On Mon, Oct 29, 2018 at 11:59 AM, Chris Jerdonek <chris.jerdonek@gmail.com> wrote:
A simpler feature that could possibly help him (assuming there isn't any external state to deal with) would be the ability to save everything at a certain point in time, and then resume it later. He could rig things up to save the state e.g. after every hour: 1 hour, 2 hours, etc. Then if an error occurs after 2.5 hours, he could at least start resuming after 2 hours. This could be viewed as a cheap form of a reverse debugger, because a reverse debugger has to save the state at every point in time, not just at a few select points.
That's very difficult to implement without help from the operating system, but there is prior art... On Unix, you can use fork() as a hacky way to do this – fork() off a process every once and a while, and have the children enter some kind of loop waiting for instructions (continue / enter debugger / exit / ...). Or, on Linux, there's: https://www.criu.org/ I also wonder if it would be useful to give pdb the ability to break when an exception is *raised*, rather than when it's caught? -n -- Nathaniel J. Smith -- https://vorpus.org

On Tue, Oct 30, 2018 at 11:10 AM Nathaniel Smith <njs@pobox.com> wrote:
I also wonder if it would be useful to give pdb the ability to break when an exception is *raised*, rather than when it's caught?
This is veering into python-ideas territory (or even python-list), but the first big concern that comes to my mind is that there are a LOT of places where exceptions are raised, and many of those exceptions end up being used for perfectly-normal flow control. So this would potentially add even more overhead to the raising of exceptions - basically, you have to retain state as if you're suspending a generator. But it'd be an extremely cool concept. Exceptions already snapshot all their locals, and this would just expand on that a bit. ChrisA

On 29Oct2018 1709, Nathaniel Smith wrote:
I also wonder if it would be useful to give pdb the ability to break when an exception is *raised*, rather than when it's caught?
This is basically the first feature I implemented as an intern at Microsoft back in 2011 :) (for Visual Studio's Python debugger) It should be in the ptvsd and PyDev.Debugger packages, so any IDEs that use those for debugging will support it (though it's not my implementation any more, as far as I know). Specifically, breaking on an exception is trivial, but filtering out the cases that have handlers on the stack is nearly impossible. We got close enough with looking at the AST of each caller that we didn't try any harder than that. If you know *where* you're expecting the exception, you could even filter on line number and then break when that line is on the stack but before unwinding. Cheers, Steve

When I have a bug that only happens after hours of run time, I try to find a much shorter test case that reproduces it. -- Greg
participants (9)
-
Armin Rigo
-
Chris Angelico
-
Chris Jerdonek
-
Ed Peschko
-
Glenn Linderman
-
Greg Ewing
-
Nathaniel Smith
-
Steve Dower
-
Steven D'Aprano