-
-
Notifications
You must be signed in to change notification settings - Fork 368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eventloop scheduling improvements for stop_on_error_timeout and schedule_next #1212
Conversation
See issue ipython#1202 - this implements the base logic, eventloops need to implement `_schedule_exit` themselves.
See issue ipython#1202, allows for returning to the kernel io_loop on a timeout
The QTimer was introduced in d4755f6 and then changed is issue ipython#990 to close a memory leak. This change makes the code more concise by removing not instancing a QTimer object but calling the static singleShot method instead
See issue ipython#1202 for _schedule_exit reasoning. Replaced `stream` as an argument with a direct reference to `kernel.shell_stream`, simplifying code. The reason for `stream` being an argument was support for multiple `kernel.shell_streams`, which has been deprecated since, see e719892
The default QTimer is coarse, so can fire within +-5% of the time specified. We _need_ to fire after the delay specified so that we exit _after_ schedule_stop_aborting is scheduled. The QTimer thus needs to be a PreciseTimer. For small values of stop_on_error_timeout I found the QTimer _still_ fired up to 5ms too early, so added 10ms of delay offset. singleShot signature is inconsistent between PySide and PyQt, so we store a timer object, similar to ipython#990
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thank you!
@ccordoba12 did you want to look at this as well? |
Yes, thanks for the ping @blink1073! I'll run our test suite against this PR and report back any issues in a couple of days. |
If the qt loop is disabled through `%gui` and then enabled again, _qt_notifier and _qt_timer stay as references to dead Qt objects, causing an error
@blink1073, just so you know, @jdranczewski is helping us to try to solve an additional issue in Spyder (referenced above), so this could take a bit longer than expected. |
Understood, thank you both! |
Hi @blink1073, while investigating spyder-ide/spyder#21299 with @ccordoba12 I found that it's not caused by #1202 but likely a slightly different issue with how ipykernel schedules the next eventloop run.
In a situation like this, I have not been able to meaningfully reproduce this in Jupyter, so this race condition may be fairly rare, but it's possible to reproduce in Spyder by spamming the run button until the request arrives at just the right time to trigger this situation, and for some users it apparently arises naturally. A fix I could suggest is putting the call to advance the eventloop on the message queue, so it's for sure only called once any dispatch events are processed: jdranczewski@30da44a What do you think of doing it this way? Do you think it should be a separate PR (as it solves a different problem than |
I'd say if it is easier for you to combine them in this PR, that is fine. |
This ensures that the msg_queue is truly empty before entering the eventloop, fixing a possible race condition where process_one has consumed a dispatch but not executed it yet. See spyder-ide/spyder#21299 and ipython#1212
Ok, in that case I think it will be easier to just continue with this PR. @ccordoba12 I've pushed the fix to this branch if you would like to run the Spyder test suite against it. I'm not sure why the linting test started failing, I have not touched the line it's now failing at... |
The lint failure is unrelated, from a typings change in ipython. |
Thanks for the update @jdranczewski! I opened spyder-ide/spyder#21834 to test your work on our side. |
@blink1073, good news! Our tests are passing without issues, so this should be ready to be merged. Also, we'd appreciate if you could release a new IPykernel version with this fix so we can depend on it in our next Spyder version. Thanks! |
Excellent! I'll make a bug release tomorrow. |
Fixes #1202 by introducing a timed exit to the Tk (on Linux) and Qt (on Windows and Linux) eventloops so
schedule_stop_aborting
can fire afterstop_on_error_timeout
in the kernel's mainio_loop
.This only affects the eventloops specified, as the others periodically hand control back to the kernel, but Tk (on Linux) and Qt normally wait for a ZMQ socket event to go back to the kernel. The
stop_on_error_timeout
does not fire a socket event, so the timer does not expire and future events are aborted when they should not.The proposed solution introduces an optional
_schedule_exit
method to eventloops that need it, and makes sure it is called if an eventloop exit is needed for thestop_on_error_timeout
to fire.