Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
As we are doing the IPython update now, I thought of this thing again and I totally forgot how complex this is. One way to solve this, is to cancel any alarm after evaluating input. That should solve the problem, but I have no idea if this is acceptable or not. I didn't find a way to see, if an alarm is scheduled (it would be nicer if one could actually raise the correct error "alarm escaped interact"). Am Donnerstag, 7. Februar 2019 17:23:18 UTC+1 schrieb E. Madison Bray: > > On Thu, Feb 7, 2019 at 5:05 PM E. Madison Bray > wrote: > > > > On Thu, Feb 7, 2019 at 4:53 PM Jeroen Demeyer > wrote: > > > > > > On 2019-02-07 16:45, E. Madison Bray wrote: > > > > Apparently Jeroen argued about this with the IPython developers some > > > > time ago: https://github.com/ipython/ipython/pull/9867 > > > > > > Indeed. Your post did seem familiar to me, but I actually forgot about > > > that discussion. > > > > FWIW we are on a rather old prompt_toolkit (1.0.9), whereas the > > current version is 2.0.7. Newer versions of IPython have also > > upgraded to depend on prompt_toolkit >= 2.0. It's possible then that > > this situation has been improved already, but I am not sure. Sage > > still uses IPython 5.x since it is an LTS release. > > Alas, I tried IPython 7 in a virtualenv and the situation is no > better. The logic for handling the KeyboardInterrupt isn't even > right: It catches the KeyboardInterrupt, then calls > self._eventloop.stop(), but then rather than break out of IPython's > mainloop function it just continues the loop and tries to call > self.interact() with a no longer functioning prompt, and then crashes. > As a bonus, leaving my terminal in an extremely broken state. > > This stuff is hard to get right, but still, no bueno... :( > -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sage-devel/d5e5eede-c9a9-4fe1-a858-f7c7b1d0b6f1o%40googlegroups.com.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Thu, Feb 7, 2019 at 5:05 PM E. Madison Bray wrote: > > On Thu, Feb 7, 2019 at 4:53 PM Jeroen Demeyer wrote: > > > > On 2019-02-07 16:45, E. Madison Bray wrote: > > > Apparently Jeroen argued about this with the IPython developers some > > > time ago: https://github.com/ipython/ipython/pull/9867 > > > > Indeed. Your post did seem familiar to me, but I actually forgot about > > that discussion. > > FWIW we are on a rather old prompt_toolkit (1.0.9), whereas the > current version is 2.0.7. Newer versions of IPython have also > upgraded to depend on prompt_toolkit >= 2.0. It's possible then that > this situation has been improved already, but I am not sure. Sage > still uses IPython 5.x since it is an LTS release. Alas, I tried IPython 7 in a virtualenv and the situation is no better. The logic for handling the KeyboardInterrupt isn't even right: It catches the KeyboardInterrupt, then calls self._eventloop.stop(), but then rather than break out of IPython's mainloop function it just continues the loop and tries to call self.interact() with a no longer functioning prompt, and then crashes. As a bonus, leaving my terminal in an extremely broken state. This stuff is hard to get right, but still, no bueno... :( -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Thu, Feb 7, 2019 at 4:53 PM Jeroen Demeyer wrote: > > On 2019-02-07 16:45, E. Madison Bray wrote: > > Apparently Jeroen argued about this with the IPython developers some > > time ago: https://github.com/ipython/ipython/pull/9867 > > Indeed. Your post did seem familiar to me, but I actually forgot about > that discussion. FWIW we are on a rather old prompt_toolkit (1.0.9), whereas the current version is 2.0.7. Newer versions of IPython have also upgraded to depend on prompt_toolkit >= 2.0. It's possible then that this situation has been improved already, but I am not sure. Sage still uses IPython 5.x since it is an LTS release. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On 2019-02-06 20:52, Nils Bruin wrote: This is the same as in python: >>> import signal >>> signal.alarm(1) 0 >>> Alarm clock It looks like this is just the default signal handler for python (the one that just prints the signal name and exits) For the record, that message "Alarm clock" is printed by the shell (bash or whatever) whenever a process that it runs (python in this case) is killed by a signal. It's analogous to the more familiar message "Segmentation Fault". -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On 2019-02-07 16:45, E. Madison Bray wrote: Apparently Jeroen argued about this with the IPython developers some time ago: https://github.com/ipython/ipython/pull/9867 Indeed. Your post did seem familiar to me, but I actually forgot about that discussion. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Thu, Feb 7, 2019 at 4:14 PM E. Madison Bray wrote: > > On Thu, Feb 7, 2019 at 4:13 PM E. Madison Bray wrote: > > > > On Wed, Feb 6, 2019 at 8:52 PM Nils Bruin wrote: > > > > > > On Wednesday, February 6, 2019 at 6:35:27 AM UTC-8, E. Madison Bray wrote: > > >> > > >> > > >> Which is being reached because AlarmInterrupt is a subclass of > > >> KeyboardInterrupt . I don't know why this doesn't happen then when, > > >> say, mashing Ctrl-C. I guess because IPython installs its own SIGINT > > >> handler or something. > > > > > > > > > In IPython proper the behaviour is different: > > > > > > > > > In [1]: import signal > > > > > > In [2]: signal.alarm(1) > > > Out[2]: 0 > > > > > > In [3]: Alarm clock > > > > > > > > > This is the same as in python: > > > > > > >>> import signal > > > >>> signal.alarm(1) > > > 0 > > > >>> Alarm clock > > > > > > It looks like this is just the default signal handler for python (the one > > > that just prints the signal name and exits) > > > > > > Note that cysignals.signals.AlarmInterrupt is our own invention, so if > > > the problem is inheriting from KeyboardInterrupt, we should probably not > > > do that. > > > > IIRC there is a good rationale for that, though I don't see it > > explicitly documented anywhere. I think it's simply that in most code > > where you would want to catch an AlarmInterrupt (i.e. you set an alarm > > on some code that should not be allowed to run for more than a certain > > amount of time), you would also likely want to break out of it > > manually with a Ctrl-C, and you would want those two cases handled the > > same. So you kill two birds with one stone this way, rather than > > having to write `except (AlarmInterrupt, KeyboardInterrupt)`. In > > other words, the AlarmInterrupt is treated sort of as an automatic > > KeyboardInterrupt on a timer. > > > > This can be avoided of course by explicitly writing `except > > (AlarmInterrupt, KeyboardInterrupt)`, but I do like the existing > > design on principle. I think in this case its better to address the > > specific problem. I find it odd that IPython would allow an interrupt > > arising from user code to break out of its event loop. It seems to > > happen in the case of code being run via signal handlers, because if I > > just enter `raise KeyboardInterrupt` at the prompt, this happens: > > > > sage: raise KeyboardInterrupt > > --- > > KeyboardInterrupt Traceback (most recent call last) > > in () > > > 1 raise KeyboardInterrupt > > > > KeyboardInterrupt: > > > > So, no problem. But I can reproduce the problem with Sage's alarm() > > using pure Python+stdlib like: > > > > sage: import signal > > sage: def raise_keyboard_interrupt(*args): > > : raise KeyboardInterrupt > > : > > sage: signal.signal(signal.SIGALRM, raise_keyboard_interrupt) > > 0 > > sage: signal.alarm(1) > > 0 > > Forgot to paste the rest of this example. Point being it does the same thing: > > > sage: import signal > sage: def raise_keyboard_interrupt(*args): > : raise KeyboardInterrupt > : > sage: signal.signal(signal.SIGALRM, raise_keyboard_interrupt) > 0 > sage: signal.alarm(1) > 0 > sage: > > KeyboardInterrupt escaped interact() > > sage: > sage: > ^[[41;1R > ** > > Oops, Sage crashed. We do our best to make it stable, but... Apparently Jeroen argued about this with the IPython developers some time ago: https://github.com/ipython/ipython/pull/9867 Part of the justification on their end seems to have more to do with prompt_toolkit, and the fact that if it is interrupted in some random state by an exception raised from a signal handler, it cannot recover to a sane state. I'm still not sure I totally buy that explanation though. Normally when you're sitting at the IPython prompt they prevent you from breaking out of the prompt because using prompt_toolkit they completely override the input handling for Ctrl-C so that it no longer sends the process a SIGINT and instead just clears the prompt. This is only true when you're sitting at the prompt though. Once you're running some Python code it restores normal input handling--you can Ctrl-C and break out of that code just fine. It's *just* when sitting at the prompt waiting for input that it blows up. I can even reproduce this simply by externally sending the process a `kill -SIGINT` while it's sitting at the prompt. This seems unreasonable to me. Even the plain readline-based Python REPL handles this just fine. It just prints "KeyboardInterrupt" and displays a new prompt. Surely it must be possible, rather than making prompt-toolkit just completely shut down, to reset its state and display a new prompt? If its state is so fragile that one interruption to its event loop is impossible to recover from that suggests that it wasn't well designed (and I don't think that's the
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Thu, Feb 7, 2019 at 4:13 PM E. Madison Bray wrote: > > On Wed, Feb 6, 2019 at 8:52 PM Nils Bruin wrote: > > > > On Wednesday, February 6, 2019 at 6:35:27 AM UTC-8, E. Madison Bray wrote: > >> > >> > >> Which is being reached because AlarmInterrupt is a subclass of > >> KeyboardInterrupt . I don't know why this doesn't happen then when, > >> say, mashing Ctrl-C. I guess because IPython installs its own SIGINT > >> handler or something. > > > > > > In IPython proper the behaviour is different: > > > > > > In [1]: import signal > > > > In [2]: signal.alarm(1) > > Out[2]: 0 > > > > In [3]: Alarm clock > > > > > > This is the same as in python: > > > > >>> import signal > > >>> signal.alarm(1) > > 0 > > >>> Alarm clock > > > > It looks like this is just the default signal handler for python (the one > > that just prints the signal name and exits) > > > > Note that cysignals.signals.AlarmInterrupt is our own invention, so if the > > problem is inheriting from KeyboardInterrupt, we should probably not do > > that. > > IIRC there is a good rationale for that, though I don't see it > explicitly documented anywhere. I think it's simply that in most code > where you would want to catch an AlarmInterrupt (i.e. you set an alarm > on some code that should not be allowed to run for more than a certain > amount of time), you would also likely want to break out of it > manually with a Ctrl-C, and you would want those two cases handled the > same. So you kill two birds with one stone this way, rather than > having to write `except (AlarmInterrupt, KeyboardInterrupt)`. In > other words, the AlarmInterrupt is treated sort of as an automatic > KeyboardInterrupt on a timer. > > This can be avoided of course by explicitly writing `except > (AlarmInterrupt, KeyboardInterrupt)`, but I do like the existing > design on principle. I think in this case its better to address the > specific problem. I find it odd that IPython would allow an interrupt > arising from user code to break out of its event loop. It seems to > happen in the case of code being run via signal handlers, because if I > just enter `raise KeyboardInterrupt` at the prompt, this happens: > > sage: raise KeyboardInterrupt > --- > KeyboardInterrupt Traceback (most recent call last) > in () > > 1 raise KeyboardInterrupt > > KeyboardInterrupt: > > So, no problem. But I can reproduce the problem with Sage's alarm() > using pure Python+stdlib like: > > sage: import signal > sage: def raise_keyboard_interrupt(*args): > : raise KeyboardInterrupt > : > sage: signal.signal(signal.SIGALRM, raise_keyboard_interrupt) > 0 > sage: signal.alarm(1) > 0 Forgot to paste the rest of this example. Point being it does the same thing: sage: import signal sage: def raise_keyboard_interrupt(*args): : raise KeyboardInterrupt : sage: signal.signal(signal.SIGALRM, raise_keyboard_interrupt) 0 sage: signal.alarm(1) 0 sage: KeyboardInterrupt escaped interact() sage: sage: ^[[41;1R ** Oops, Sage crashed. We do our best to make it stable, but... -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Wed, Feb 6, 2019 at 8:52 PM Nils Bruin wrote: > > On Wednesday, February 6, 2019 at 6:35:27 AM UTC-8, E. Madison Bray wrote: >> >> >> Which is being reached because AlarmInterrupt is a subclass of >> KeyboardInterrupt . I don't know why this doesn't happen then when, >> say, mashing Ctrl-C. I guess because IPython installs its own SIGINT >> handler or something. > > > In IPython proper the behaviour is different: > > > In [1]: import signal > > In [2]: signal.alarm(1) > Out[2]: 0 > > In [3]: Alarm clock > > > This is the same as in python: > > >>> import signal > >>> signal.alarm(1) > 0 > >>> Alarm clock > > It looks like this is just the default signal handler for python (the one > that just prints the signal name and exits) > > Note that cysignals.signals.AlarmInterrupt is our own invention, so if the > problem is inheriting from KeyboardInterrupt, we should probably not do that. IIRC there is a good rationale for that, though I don't see it explicitly documented anywhere. I think it's simply that in most code where you would want to catch an AlarmInterrupt (i.e. you set an alarm on some code that should not be allowed to run for more than a certain amount of time), you would also likely want to break out of it manually with a Ctrl-C, and you would want those two cases handled the same. So you kill two birds with one stone this way, rather than having to write `except (AlarmInterrupt, KeyboardInterrupt)`. In other words, the AlarmInterrupt is treated sort of as an automatic KeyboardInterrupt on a timer. This can be avoided of course by explicitly writing `except (AlarmInterrupt, KeyboardInterrupt)`, but I do like the existing design on principle. I think in this case its better to address the specific problem. I find it odd that IPython would allow an interrupt arising from user code to break out of its event loop. It seems to happen in the case of code being run via signal handlers, because if I just enter `raise KeyboardInterrupt` at the prompt, this happens: sage: raise KeyboardInterrupt --- KeyboardInterrupt Traceback (most recent call last) in () > 1 raise KeyboardInterrupt KeyboardInterrupt: So, no problem. But I can reproduce the problem with Sage's alarm() using pure Python+stdlib like: sage: import signal sage: def raise_keyboard_interrupt(*args): : raise KeyboardInterrupt : sage: signal.signal(signal.SIGALRM, raise_keyboard_interrupt) 0 sage: signal.alarm(1) 0 I'm just not entirely user that the KeyboardInterrupt handling in IPython is entirely well considered here. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Wednesday, February 6, 2019 at 6:35:27 AM UTC-8, E. Madison Bray wrote: > > > Which is being reached because AlarmInterrupt is a subclass of > KeyboardInterrupt . I don't know why this doesn't happen then when, > say, mashing Ctrl-C. I guess because IPython installs its own SIGINT > handler or something. > In IPython proper the behaviour is different: In [1]: import signal In [2]: signal.alarm(1) Out[2]: 0 In [3]: Alarm clock This is the same as in python: >>> import signal >>> signal.alarm(1) 0 >>> Alarm clock It looks like this is just the default signal handler for python (the one that just prints the signal name and exits) Note that cysignals.signals.AlarmInterrupt is our own invention, so if the problem is inheriting from KeyboardInterrupt, we should probably not do that. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.
Re: [sage-devel] AlarmInterrupt causes Sage to crash hard
On Wed, Feb 6, 2019 at 10:29 AM jonathan.kliem via sage-devel wrote: > > sage: alarm(1) > sage: > > AlarmInterrupt escaped interact() > > sage: > sage: > ^[[50;1R > ** > > Oops, Sage crashed. We do our best to make it stable, but... > > ... > > Is this supposed to happen? I think obviously not :) I can confirm the same. It's not clear how long this has been the case--it looks to me like a bug/oddity in IPython? The exception is originating from IPython.terminal.interactiveshell which contains the following: def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED): # An extra layer of protection in case someone mashing Ctrl-C breaks # out of our internal code. if display_banner is not DISPLAY_BANNER_DEPRECATED: warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2) while True: try: self.interact() break except KeyboardInterrupt as e: print("\n%s escaped interact()\n" % type(e).__name__) finally: # An interrupt during the eventloop will mess up the # internal state of the prompt_toolkit library. # Stopping the eventloop fixes this, see # https://github.com/ipython/ipython/pull/9867 if hasattr(self, '_eventloop'): self._eventloop.stop() Which is being reached because AlarmInterrupt is a subclass of KeyboardInterrupt . I don't know why this doesn't happen then when, say, mashing Ctrl-C. I guess because IPython installs its own SIGINT handler or something. -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.