robotpy / robotpy-wpilib

Moved to https://github.com/robotpy/mostrobotpy
https://robotpy.github.io
Other
169 stars 59 forks source link

CTRL-C in gui on Linux segfaults #689

Closed virtuald closed 2 years ago

virtuald commented 3 years ago

I've been playing with this but I think I give up. If I CTRL-C the gui, it doesn't do anything until I close the window, at which point this shows up:

^CTraceback (most recent call last):
  File "/home/virtuald/src/frc/examples/commands-v2/ramsete/./robot.py", line 65, in <module>
    wpilib.run(MyRobot)
  File "/home/virtuald/src/frc/robotpy-wpilib/wpilib/_impl/main.py", line 193, in run
    retval = options.cmdobj.run(options, robot_class, **kwargs)
  File "/home/virtuald/src/frc/pyfrc/pyfrc/mains/cli_sim.py", line 80, in run
    return robot_class.main(robot_class)
  File "/home/virtuald/src/frc/robotpy-wpilib/wpilib/_impl/start.py", line 37, in run
    hal.runMain()
KeyboardInterrupt
terminate called without an active exception
Fatal Python error: Aborted

Thread 0x00007fb8ad1ce740 (most recent call first):
<no Python frame>
Aborted (core dumped)

I had thought maybe the right way to deal with it is add the following to robotpy-hal:

  // add a simulation periodic handler that checks to see if python needs
  // to handle any signals. Only done in simulation mode.
  HALSIM_RegisterSimPeriodicBeforeCallback(
      [](void *) {
        py::gil_scoped_acquire gil;
        if (PyErr_CheckSignals()) {
          throw py::error_already_set();
        }
      },
      nullptr);

It seems that PyErr_CheckSignals never returned non-zero. I played with a variety of things, but nothing really stuck.

I did add a signal handler right before hal.runMain() is called, and that prevents the segfault from occurring, but the application still doesn't end. Interestingly enough, the signal handler doesn't get called until after the window is closed. Probably because of this:

A long-running calculation implemented purely in C (such as regular expression matching on a large body of text) may run uninterrupted for an arbitrary amount of time, regardless of any signals received. The Python signal handlers will be called when the calculation finishes.

So here it is:

def _on_ctrl_c(*ignored):
    hal.exitMain()

signal.signal(signal.SIGINT, _on_ctrl_c)

I guess it does solve the segfault, but it feels like a bad idea. Not sure what happens on Windows/OSX.

virtuald commented 2 years ago

Fixed in https://github.com/robotpy/robotpy-halsim-gui/pull/10