Interrupting

Jean Brouwers wrote:

We're using the Py Shell include with wxPython to run commands in a Python interpreter inside a wxPython window pane. We need to be able to interrupt a long command running in the interpreter, Using Ctrl+C and catching the KeyboardInterrupt is not working.

The PyShell does have a key down event handler for Ctrl+C which could handle the key but that does not seem to be the problem. As far as we can tell, the event handler is not even called while the Python interpreter is busy. It looks more like the key event is pending inside wxPyhon or somewhere else.

The question is (1) why is this not working

The flow of control must return from the current event handler back to the event loop before any more events can be delivered. Since the current handler is stuck executing Python code then you can't get any more events until it is finished, or control is yielded back to the event loop in some other way.

and (2) how can such an interrupt from the keyboard be handled in wxPython?

You'll need to find a way to hook into the normal execution of Python code so that PyShell can check if it needs to raise an exception to get out of the running code. Perhaps the sys.settrace function (used by the debugger) can be used to set a function that gets called while executing and you can do something there. However the real trick is to find a way to signal that the code should be terminated, but not process any other events that might put things in a funky state when control returns normally, and that doesn't take very long to do since the trace function will get called a lot.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Some further thoughts on this and trying to answer our own questions.

Normally, in other Python applications Ctrl+C raises the SIGINT signal which is handled by Python and turned into a KeyboardInterrupt exception. That does not seem to happen in a wxPython application, with or without the Py Shell. If we hit Ctrl+C in the C shell window where the wxPython application was invoked, the application terminates without printing the Python exception and traceback. So, it looks like the regular SIGINT signal handling by Python is disabled or maybe caught by wxPython.

One way to handle interrupt might be to run the wxPython/PyShell code and the Python interpreter in different threads. That would be needed anyway to prevent wxPython/PyShell from blocking while a command is running in the Python interpreter. Any key stroke can then be used to interrupt the running command and throw a KeyboardInterrupt exception. That may be the best way to go, provided wxPython does not catch the exception.

The first issue remains though, what is happening to the reqgular SIGINT signal in wxPython? This is wxPython on GTK2 and Linux.

/Jean Brouwers

Robin Dunn wrote:

···

Jean Brouwers wrote:

We're using the Py Shell include with wxPython to run commands in a Python interpreter inside a wxPython window pane. We need to be able to interrupt a long command running in the interpreter, Using Ctrl+C and catching the KeyboardInterrupt is not working.

The PyShell does have a key down event handler for Ctrl+C which could handle the key but that does not seem to be the problem. As far as we can tell, the event handler is not even called while the Python interpreter is busy. It looks more like the key event is pending inside wxPyhon or somewhere else.

The question is (1) why is this not working

The flow of control must return from the current event handler back to the event loop before any more events can be delivered. Since the current handler is stuck executing Python code then you can't get any more events until it is finished, or control is yielded back to the event loop in some other way.

and (2) how can such an interrupt from the keyboard be handled in wxPython?

You'll need to find a way to hook into the normal execution of Python code so that PyShell can check if it needs to raise an exception to get out of the running code. Perhaps the sys.settrace function (used by the debugger) can be used to set a function that gets called while executing and you can do something there. However the real trick is to find a way to signal that the code should be terminated, but not process any other events that might put things in a funky state when control returns normally, and that doesn't take very long to do since the trace function will get called a lot.

What about this surprise?

Test #1

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.getsignal(signal.SIGINT)
<built-in function default_int_handler> # as expected
>>> import wx
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped) # wow!

Test #2

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> import signal
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped)

Ergo, wxPython 2.4.1.2 must be doing something to signals (on GTK2 and Linux).

/Jean Brouwers

Jean Brouwers wrote:

···

Some further thoughts on this and trying to answer our own questions.

Normally, in other Python applications Ctrl+C raises the SIGINT signal which is handled by Python and turned into a KeyboardInterrupt exception. That does not seem to happen in a wxPython application, with or without the Py Shell. If we hit Ctrl+C in the C shell window where the wxPython application was invoked, the application terminates without printing the Python exception and traceback. So, it looks like the regular SIGINT signal handling by Python is disabled or maybe caught by wxPython.

One way to handle interrupt might be to run the wxPython/PyShell code and the Python interpreter in different threads. That would be needed anyway to prevent wxPython/PyShell from blocking while a command is running in the Python interpreter. Any key stroke can then be used to interrupt the running command and throw a KeyboardInterrupt exception. That may be the best way to go, provided wxPython does not catch the exception.

The first issue remains though, what is happening to the reqgular SIGINT signal in wxPython? This is wxPython on GTK2 and Linux.

/Jean Brouwers

Robin Dunn wrote:

Jean Brouwers wrote:

We're using the Py Shell include with wxPython to run commands in a Python interpreter inside a wxPython window pane. We need to be able to interrupt a long command running in the interpreter, Using Ctrl+C and catching the KeyboardInterrupt is not working.

The PyShell does have a key down event handler for Ctrl+C which could handle the key but that does not seem to be the problem. As far as we can tell, the event handler is not even called while the Python interpreter is busy. It looks more like the key event is pending inside wxPyhon or somewhere else.

The question is (1) why is this not working

The flow of control must return from the current event handler back to the event loop before any more events can be delivered. Since the current handler is stuck executing Python code then you can't get any more events until it is finished, or control is yielded back to the event loop in some other way.

and (2) how can such an interrupt from the keyboard be handled in wxPython?

You'll need to find a way to hook into the normal execution of Python code so that PyShell can check if it needs to raise an exception to get out of the running code. Perhaps the sys.settrace function (used by the debugger) can be used to set a function that gets called while executing and you can do something there. However the real trick is to find a way to signal that the code should be terminated, but not process any other events that might put things in a funky state when control returns normally, and that doesn't take very long to do since the trace function will get called a lot.

Jean Brouwers wrote:

Some further thoughts on this and trying to answer our own questions.

Normally, in other Python applications Ctrl+C raises the SIGINT signal which is handled by Python and turned into a KeyboardInterrupt exception. That does not seem to happen in a wxPython application, with or without the Py Shell.

Correct. Because GUIs do not normally receive characters from the tty's standard input device, they get them as events from the UI system, which bypasses turning Ctrl-C into a SIGINT.

If we hit Ctrl+C in the C shell window where the wxPython application was invoked, the application terminates without printing the Python exception and traceback. So, it looks like the regular SIGINT signal handling by Python is disabled or maybe caught by wxPython.

Yep. Look in wx.App.__init__. It resets the SIGINT handler back to the default handler. This is done to work around a problem where the Ctrl-C woudl appear to not do anything at all until your app exits, and then it will segfault as Python finally gets around to processing the signal but it is too far down the shutdown path to be able to do handle it properly. (This may be some interaction with GTK that is causing this delayed reaction, or perhaps the way that current threadstate is being managed...) By resetting it to the default handler then the app will terminate when Ctrl-C is pressing the in the terminal just like every other X-Windows app that I have tried it with. (In 2.5 you can turn this off with a parameter to __init__.)

One way to handle interrupt might be to run the wxPython/PyShell code and the Python interpreter in different threads. That would be needed anyway to prevent wxPython/PyShell from blocking while a command is running in the Python interpreter. Any key stroke can then be used to interrupt the running command and throw a KeyboardInterrupt exception. That may be the best way to go, provided wxPython does not catch the exception.

Yes, unless the Python code being executed by the shell is doing stuff with the GUI. Then you'll want to make sure that at least those method calls happen in the main thread.

BTW, don't let my remarks make you think that I am against any changes in this area. If something can safely be done about this I am very interested in getting updates for an interruptable PyShell.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin,

Thank you for your comments and suggestions.

One additional option we may consider is running the Python interpreter as a separate process (on the same or maybe even a different machine). The Py Shell acts then like terminal window to a Python command line. We may loose some of the nice features of Py but that remains to be determined and traded off.

We will be busy with this one for a while and will keep you posted on our progress. Or lack thereof ... :wink:

/Jean Brouwers

PS) Patrick O'Brien responded in a separate post and gave some more details one using sys.settrace().

Robin Dunn wrote:

···

Jean Brouwers wrote:

Robin,

Keeping in mind the application requirements you mentioned, below are two potential solutions to make the Py Shell interruptable. Both should work for all application command regardless whether the command makes further wxPython calls or not.

A) Just before invoking the command the Py Shell installs the SIGINT signal handler, probably the default Python one which throws the KeyboardInterrupt exception. The command must be invoked inside a try-except suite to catch to KeyboardInterrupt. After the command finished, the default wxPython handler is re-installed. This should work for most Python applications which allow/expect interrupts. The main requiment is that the application command terminates on a KeyboardInterrupt or re-raises the KeyboardInterrupt after catching it.

B) Before invoking the command, the Py Shell starts a very thread which sets up the SIGINT signal handler (and maybe collects other keyboard input). If an interrupt occurs, the thread forwards the interrupt to the main thread (using the interrupt_main() method from Python 2.3). The advantage here is that any keystroke could be defined as interrupt, not just those pre-defined by the underlying platform. Also, the thread might even show a dialog with a few buttons to interrupt or cancel the command. The dialog would only show up after some short (but configurable) time period has expired.

We will try the first option mentioned above unless there is reason that it won't work**.

I think you'll still have problems getting the SIGINT. The fact that it was misbehaving in wxPython apps was the reason that it was disabled in the first place. I think you'll have to catch an event some other way.

Assuming they work, both solution do not address the non-responsive user interface problem. The wxPython user inface appears blocked during long running commands.

The only way to resolve that is to either return as quickly as possible to the MainLoop from the event handler that started executing the code, or to periodically call wx.YeildIfNeeded from within the long running code. Returning immediatly implies using a thread to run the statement, which has the problem I've already mentioned of not being safe for running wx code. Yielding implies hooking into the interpreter somehow[*] to call the yeild, but it also has the potential problem of becoming recursive as the shell tries to process more key or mouse events so you would have to block all events except the ones you are looking for.

[*] The sys.settrace I mentioned before might work, but could interfere with running a Python debugger. Another possibility is to make the assumption that the long running code will be periodically printing something, and since the sys.stdout is already being captured by the shell you could do something in py.Shell.writeOut.

About two months ago, we exchanged a couple of posts about handling interrupt in a wxPython application. In the mean time, we have done a little more work on this issue and the results are below.

We copied the clearSigInt code from wx.App.__init__ in 2.5.x to our App.OnInit() method and tried different cases as indicate by the numbered comments below.

class App(wx.App):
    ....
    def OnInit(self):
         # copied from wx.App.__init__() in wxPython 2.5.x
         # file wxPythonSrc-2.5,x/wxPython/src/_app_ex.py
        if True: # clearSigInt:
            try:
                import signal
#1 signal.signal(signal.SIGINT, signal.SIG_DFL) # behaves as expected
#2 signal.signal(signal.SIGINT, signal.SIG_IGN) # surprise, Ctrl-C does interrupt
#3 signal.signal(signal.SIGINT, signal.default_int_handler) # crashes on Ctrl+C
            except:
                pass

It turns out that both cases #1 and #2 behave exactly the same as the default behavior in wxPython 2.4.1.2: hitting Ctrl+C in the terminal window interrupts the application, always. This is unexpected for case #2, since Ctrl+C should have no effect.

However, case #3 crashes the application with a segmentation fault after Ctrl+C is typed in the terminal window. Attached is the traceback from the core file and it does appear that there is a problem in Python. But it does not seem to be related to SIG_DFL being zero, as far as we can tell.

In addition, printing the value returned by the signal.signal() call does not show anything, not 0, not 1, nothing. It looks like an empty string but repr() does not show anything either.

We are not sure what to make of this and hope this might be helpful to you.

/Jean Brouwers
ProphICy Semiconductor, Inc.

PS) This is wxPython 2.4.1.2 and Python 2.3 on RedHat Linux 8 with GTK2.

Robin Dunn wrote:

crash.txt (13.7 KB)

···

Jean Brouwers wrote:

What about this surprise?

Test #1

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.getsignal(signal.SIGINT)
<built-in function default_int_handler> # as expected
>>> import wx
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped) # wow!

Yep. This is a bug in Python. wx.App.__init__ sets the signal handler to SIG_DFL (which is zero in C) and then when you call getsignal Python tries to turn the pointer it gets (NULL) into a PyObject to return. It would normally be some callable python object, but in this case Python ends up dereferencing a NULL pointer and crashing.

I'm pretty sure I entered this into the Python bug tracker, or found it there already, although I can't find it right now. If you have time you might try looking for it and entering it again if not found so it can be fixed before 2.4.

Attached is the traceback for the original seg fault, mentioned in an email from several months ago, included below.

This crash occurs at a different locations than the one sent earlier today. We hope this helps as well.

/Jean Brouwers
ProphICy Semiconductor, Inc.

Robin Dunn wrote:

crash2.txt (6.6 KB)

···

Jean Brouwers wrote:

What about this surprise?

Test #1

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.getsignal(signal.SIGINT)
<built-in function default_int_handler> # as expected
>>> import wx
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped) # wow!

Yep. This is a bug in Python. wx.App.__init__ sets the signal handler to SIG_DFL (which is zero in C) and then when you call getsignal Python tries to turn the pointer it gets (NULL) into a PyObject to return. It would normally be some callable python object, but in this case Python ends up dereferencing a NULL pointer and crashing.

I'm pretty sure I entered this into the Python bug tracker, or found it there already, although I can't find it right now. If you have time you might try looking for it and entering it again if not found so it can be fixed before 2.4.

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError. Hitting Cltr+C at that time results in a crash, consistently and repeatably.

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT. Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the signalmodule.c file. The latter restores all signal handlers to their original state and wipes out the C globals used in the signalmodule.c which were initially set by Py_InitInterrupts(). In particular globals IntHandler, IgnoreHandler, and DefaultHandler are set to NULL by PyOS_FiniInterrupts().

This does not look like a bug in Python. Rather, wxPython should not call PyOS_FiniInterrupt(). Instead, wxPyhon should call other Python signal functions to achieve what wxPython needs (is that just resetting the SIGINT handler to SIG_IGN?). Or maybe call PyOS_InitInterrupts() again to re-initialize the globals Python needs (but may cause other problems, like redefining all attributes of the Python signal module).

Both suggestions are guesses on our part, but we do suspect that the call to PyOS_FiniInterrupts() is the root cause of the signal crashes. And that call breaks all further signal handling in Python, forever.

We are looking forward to your take on this and corrections of any misunderstanding on our part.

/Jean Brouwers
ProphICy Semiconductor, Inc.

*) That comp.lang.python thread is here:

<http://groups.google.com/groups?hl=en&lr=&threadm=mailman.6323.1100306430.5135.python-list%40python.org&prev=/groups%3Fhl%3Den%26lr%3D%26group%3Dcomp.lang.python&gt;

**) The traceback from on Oct 31 is also at

<http://lists.wxwidgets.org/cgi-bin/ezmlm-cgi?11:msp:33432:leapomhlkkagbceihodl&gt;

Jean Brouwers wrote:

···

About two months ago, we exchanged a couple of posts about handling interrupt in a wxPython application. In the mean time, we have done a little more work on this issue and the results are below.

We copied the clearSigInt code from wx.App.__init__ in 2.5.x to our App.OnInit() method and tried different cases as indicate by the numbered comments below.

class App(wx.App):
   ....
   def OnInit(self):
        # copied from wx.App.__init__() in wxPython 2.5.x
        # file wxPythonSrc-2.5,x/wxPython/src/_app_ex.py
       if True: # clearSigInt:
           try:
               import signal
#1 signal.signal(signal.SIGINT, signal.SIG_DFL) # behaves as expected
#2 signal.signal(signal.SIGINT, signal.SIG_IGN) # surprise, Ctrl-C does interrupt
#3 signal.signal(signal.SIGINT, signal.default_int_handler) # crashes on Ctrl+C
           except:
               pass

It turns out that both cases #1 and #2 behave exactly the same as the default behavior in wxPython 2.4.1.2: hitting Ctrl+C in the terminal window interrupts the application, always. This is unexpected for case #2, since Ctrl+C should have no effect.

However, case #3 crashes the application with a segmentation fault after Ctrl+C is typed in the terminal window. Attached is the traceback from the core file and it does appear that there is a problem in Python. But it does not seem to be related to SIG_DFL being zero, as far as we can tell.

In addition, printing the value returned by the signal.signal() call does not show anything, not 0, not 1, nothing. It looks like an empty string but repr() does not show anything either.

We are not sure what to make of this and hope this might be helpful to you.

/Jean Brouwers
ProphICy Semiconductor, Inc.

PS) This is wxPython 2.4.1.2 and Python 2.3 on RedHat Linux 8 with GTK2.

Robin Dunn wrote:

Jean Brouwers wrote:

What about this surprise?

Test #1

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.getsignal(signal.SIGINT)
<built-in function default_int_handler> # as expected
>>> import wx
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped) # wow!

Yep. This is a bug in Python. wx.App.__init__ sets the signal handler to SIG_DFL (which is zero in C) and then when you call getsignal Python tries to turn the pointer it gets (NULL) into a PyObject to return. It would normally be some callable python object, but in this case Python ends up dereferencing a NULL pointer and crashing.

I'm pretty sure I entered this into the Python bug tracker, or found it there already, although I can't find it right now. If you have time you might try looking for it and entering it again if not found so it can be fixed before 2.4.

------------------------------------------------------------------------

Traceback of the segmentation fault after Ctrl+C when restoring the default SIGINT
handler with signal.signal(signal.SIG_INT, signal.default_int_handler) in the OnInit()
method of the main App(wx.App) class of a Python 2.3 and wxPython 2.4.1.2 application.

/Jean Brouwers
ProphICy Semiconductor, Inc.

[ProphICy ~/src]$ gdb /ProphICy/bin/python core.23994
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...

warning: core file may not match specified executable file.
Core was generated by `/ProphICy/bin/python runGui.py ..'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/i686/libpthread.so.0...done.
Loaded symbols for /lib/i686/libpthread.so.0
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libutil.so.1...done.
Loaded symbols for /lib/libutil.so.1
Reading symbols from /usr/lib/libstdc++.so.5...done.
Loaded symbols for /usr/lib/libstdc++.so.5
Reading symbols from /lib/i686/libm.so.6...done.
Loaded symbols for /lib/i686/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/strop.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/strop.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/time.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/time.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cStringIO.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cStringIO.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/fcntl.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/fcntl.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/select.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/select.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/termios.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/termios.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/resource.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/resource.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_socket.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_socket.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_ssl.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_ssl.so
Reading symbols from /lib/libssl.so.2...done.
Loaded symbols for /lib/libssl.so.2
Reading symbols from /lib/libcrypto.so.2...done.
Loaded symbols for /lib/libcrypto.so.2
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_weakref.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_weakref.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/operator.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/operator.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/math.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/math.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/itertools.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/itertools.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cPickle.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cPickle.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/wxc.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/wxc.so
Reading symbols from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so...done.
Loaded symbols for /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
Reading symbols from /usr/lib/libgtk-x11-2.0.so.0...done.
Loaded symbols for /usr/lib/libgtk-x11-2.0.so.0
Reading symbols from /usr/lib/libgdk-x11-2.0.so.0...done.
Loaded symbols for /usr/lib/libgdk-x11-2.0.so.0
Reading symbols from /usr/lib/libatk-1.0.so.0...done.
Loaded symbols for /usr/lib/libatk-1.0.so.0
Reading symbols from /usr/lib/libgdk_pixbuf-2.0.so.0...done.
Loaded symbols for /usr/lib/libgdk_pixbuf-2.0.so.0
Reading symbols from /usr/lib/libpangoxft-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangoxft-1.0.so.0
Reading symbols from /usr/lib/libpangox-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangox-1.0.so.0
Reading symbols from /usr/lib/libpango-1.0.so.0...done.
Loaded symbols for /usr/lib/libpango-1.0.so.0
Reading symbols from /usr/lib/libgobject-2.0.so.0...done.
Loaded symbols for /usr/lib/libgobject-2.0.so.0
Reading symbols from /usr/lib/libgmodule-2.0.so.0...done.
Loaded symbols for /usr/lib/libgmodule-2.0.so.0
Reading symbols from /usr/lib/libgthread-2.0.so.0...done.
Loaded symbols for /usr/lib/libgthread-2.0.so.0
Reading symbols from /usr/lib/libglib-2.0.so.0...done.
Loaded symbols for /usr/lib/libglib-2.0.so.0
Reading symbols from /usr/lib/libpangoft2-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangoft2-1.0.so.0
Reading symbols from /usr/X11R6/lib/libXi.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXi.so.6
Reading symbols from /usr/X11R6/lib/libXext.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXext.so.6
Reading symbols from /usr/lib/libXft.so.2...done.
Loaded symbols for /usr/lib/libXft.so.2
Reading symbols from /usr/X11R6/lib/libXrender.so.1...done.
Loaded symbols for /usr/X11R6/lib/libXrender.so.1
Reading symbols from /usr/lib/libfontconfig.so.1...done.
Loaded symbols for /usr/lib/libfontconfig.so.1
Reading symbols from /usr/X11R6/lib/libX11.so.6...done.
Loaded symbols for /usr/X11R6/lib/libX11.so.6
Reading symbols from /usr/lib/libfreetype.so.6...done.
Loaded symbols for /usr/lib/libfreetype.so.6
Reading symbols from /usr/lib/libexpat.so.0...done.
Loaded symbols for /usr/lib/libexpat.so.0
Reading symbols from /usr/X11R6/lib/X11/locale/common/xlcUTF8Load.so.2...done.
Loaded symbols for /usr/X11R6/lib/X11/locale/common/xlcUTF8Load.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /usr/lib/gtk-2.0/2.0.0/engines/libbluecurve.so...done.
Loaded symbols for /usr/lib/gtk-2.0/2.0.0/engines/libbluecurve.so
Reading symbols from /usr/lib/gconv/ISO8859-1.so...done.
Loaded symbols for /usr/lib/gconv/ISO8859-1.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_locale.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_locale.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/htmlc.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/htmlc.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/gridc.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/gridc.so
Reading symbols from /usr/lib/pango/1.1.0/modules/pango-basic-xft.so...done.
Loaded symbols for /usr/lib/pango/1.1.0/modules/pango-basic-xft.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/stc_c.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/stc_c.so
#0 PyEval_EvalCodeEx (co=0x406a3ae0, globals=0x835b3d0, locals=0x0, args=0x4166c1d8, argcount=2,
   kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2493
2493 Py_INCREF(x);

(gdb) backtrace
#0 PyEval_EvalCodeEx (co=0x406a3ae0, globals=0x835b3d0, locals=0x0, args=0x4166c1d8, argcount=2,
   kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2493
#1 0x080ec871 in function_call (func=0x41808ca4, arg=0x4166c1cc, kw=0x0) at Objects/funcobject.c:504
#2 0x0805b058 in PyObject_Call (func=0x0, arg=0x4166c1cc, kw=0x0) at Objects/abstract.c:1755
#3 0x080610f0 in instancemethod_call (func=0x41808ca4, arg=0x4166c1cc, kw=0x0)
   at Objects/classobject.c:2432
#4 0x0805b058 in PyObject_Call (func=0x0, arg=0x406a136c, kw=0x0) at Objects/abstract.c:1755
#5 0x080a4307 in PyEval_CallObjectWithKeywords (func=0x418037d4, arg=0x406a136c, kw=0x0)
   at Python/ceval.c:3346
#6 0x40825cc7 in wxPyCallback::EventThunker(wxEvent&) (this=0x841a4d0, event=@0x406a136c)
   at src/helpers.cpp:1246
#7 0x40cc23b2 in wxEvtHandler::SearchDynamicEventTable(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#8 0x40cc1e99 in wxEvtHandler::ProcessEvent(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#9 0x40c2cc52 in wxApp::SendIdleEvents(wxWindow*) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#10 0x40c2cb90 in wxApp::SendIdleEvents() ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#11 0x40c2cb3f in wxApp::OnIdle(wxIdleEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#12 0x40cc212a in wxEvtHandler::SearchEventTable(wxEventTable&, wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#13 0x40cc1edb in wxEvtHandler::ProcessEvent(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#14 0x40c2cab1 in wxApp::ProcessIdle() () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#15 0x40c2c3af in wxapp_idle_callback () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#16 0x412f2c83 in g_idle_dispatch () from /usr/lib/libglib-2.0.so.0
#17 0x412eff65 in g_main_dispatch () from /usr/lib/libglib-2.0.so.0
#18 0x412f0f98 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#19 0x412f12ad in g_main_context_iterate () from /usr/lib/libglib-2.0.so.0
#20 0x412f1a1f in g_main_loop_run () from /usr/lib/libglib-2.0.so.0
#21 0x4102939f in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#22 0x40c2cce2 in wxApp::MainLoop() () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#23 0x40822f23 in wxPyApp::MainLoop() (this=0x83fc1b0) at src/helpers.cpp:131
#24 0x4082c546 in _wrap_wxPyApp_MainLoop (self=0x0, args=0x406a134c, kwargs=0x406a2714)
   at src/gtk/wx.cpp:1383
#25 0x080ecc78 in PyCFunction_Call (func=0x4069ea0c, arg=0x406a134c, kw=0x2)
   at Objects/methodobject.c:108
#26 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a134c, kw=0x406a2714)
   at Objects/abstract.c:1755
#27 0x080a49d9 in ext_do_call (func=0x4069ea0c, pp_stack=0xbfffd07c, flags=1, na=1, nk=0)
   at Python/ceval.c:3713
#28 0x080a2e76 in eval_frame (f=0x8229c6c) at Python/ceval.c:2151
#29 0x080a357a in PyEval_EvalCodeEx (co=0x4062fda0, globals=0x406a134c, locals=0x0, args=0x406a1318,
   argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2663
#30 0x080ec871 in function_call (func=0x4164f1ec, arg=0x406a130c, kw=0x0) at Objects/funcobject.c:504
#31 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a130c, kw=0x0) at Objects/abstract.c:1755
#32 0x080610f0 in instancemethod_call (func=0x4164f1ec, arg=0x406a130c, kw=0x0)
   at Objects/classobject.c:2432
#33 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a130c, kw=0x0) at Objects/abstract.c:1755
#34 0x080a4743 in do_call (func=0x417ed93c, pp_stack=0xbfffd4ac, na=1, nk=1080693516)
   at Python/ceval.c:3644
#35 0x080a43ef in call_function (pp_stack=0xbfffd4ac, oparg=1080693516) at Python/ceval.c:3460
#36 0x080a2a48 in eval_frame (f=0x819eca4) at Python/ceval.c:2116
#37 0x080a467d in fast_function (func=0x2, pp_stack=0xbfffd5dc, n=1, na=1, nk=0)
   at Python/ceval.c:3518
#38 0x080a445f in call_function (pp_stack=0xbfffd5dc, oparg=1080693516) at Python/ceval.c:3458
#39 0x080a2a48 in eval_frame (f=0x815a9a4) at Python/ceval.c:2116
#40 0x080a357a in PyEval_EvalCodeEx (co=0x4042ce20, globals=0x406a130c, locals=0x0, args=0x815aaf0,
   argcount=1, kws=0x81939d4, kwcount=1, defs=0x404d96f8, defcount=1, closure=0x0)
   at Python/ceval.c:2663
#41 0x080a4601 in fast_function (func=0x2, pp_stack=0xbfffd77c, n=3, na=1, nk=135870932)
   at Python/ceval.c:3529
#42 0x080a445f in call_function (pp_stack=0xbfffd77c, oparg=1080693516) at Python/ceval.c:3458
#43 0x080a2a48 in eval_frame (f=0x819386c) at Python/ceval.c:2116
#44 0x080a467d in fast_function (func=0x2, pp_stack=0xbfffd8ac, n=0, na=0, nk=0)
   at Python/ceval.c:3518
#45 0x080a445f in call_function (pp_stack=0xbfffd8ac, oparg=1080693516) at Python/ceval.c:3458
#46 0x080a2a48 in eval_frame (f=0x812ac7c) at Python/ceval.c:2116
#47 0x080a357a in PyEval_EvalCodeEx (co=0x40196760, globals=0x406a130c, locals=0x4016f79c, args=0x0,
   argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2663
#48 0x080a5b06 in PyEval_EvalCode (co=0x40196760, globals=0x4016f79c, locals=0x4016f79c)
   at Python/ceval.c:537
#49 0x080caee9 in run_node (n=0x40158338, filename=0xbffff76a "runGui.py", globals=0x4016f79c,
   locals=0x4016f79c, flags=0xbfffda08) at Python/pythonrun.c:1205
#50 0x080ca795 in PyRun_SimpleFileExFlags (fp=0x8128b28, filename=0xbffff76a "runGui.py", closeit=1,
   flags=0xbfffda08) at Python/pythonrun.c:802
#51 0x08054c6e in Py_Main (argc=0, argv=0xbfffda84) at Modules/main.c:415
#52 0x080547e7 in main (argc=4, argv=0xbfffda84) at Modules/python.c:23
#53 0x420158f7 in __libc_start_main () from /lib/i686/libc.so.6
(gdb) quit

------------------------------------------------------------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Two additions and two corrections:

- This is wxPython 2.4.1.2 and Python 2.3 on RedHat Linux 8 with GTK2.

- PyOS_FiniInterrupts() is not called in wxPython 2.5.3.1.

- Cltr+C should be Ctrl+C.

- Py_InitInterrupts() should be PyOS_InitInterrupts().

/Jean Brouwers
ProphICy Semiconductor, Inc.

Jean Brouwers wrote:

···

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError. Hitting Cltr+C at that time results in a crash, consistently and repeatably.

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT. Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the signalmodule.c file. The latter restores all signal handlers to their original state and wipes out the C globals used in the signalmodule.c which were initially set by Py_InitInterrupts(). In particular globals IntHandler, IgnoreHandler, and DefaultHandler are set to NULL by PyOS_FiniInterrupts().

This does not look like a bug in Python. Rather, wxPython should not call PyOS_FiniInterrupt(). Instead, wxPyhon should call other Python signal functions to achieve what wxPython needs (is that just resetting the SIGINT handler to SIG_IGN?). Or maybe call PyOS_InitInterrupts() again to re-initialize the globals Python needs (but may cause other problems, like redefining all attributes of the Python signal module).

Both suggestions are guesses on our part, but we do suspect that the call to PyOS_FiniInterrupts() is the root cause of the signal crashes. And that call breaks all further signal handling in Python, forever.

We are looking forward to your take on this and corrections of any misunderstanding on our part.

/Jean Brouwers
ProphICy Semiconductor, Inc.

*) That comp.lang.python thread is here:

<http://groups.google.com/groups?hl=en&lr=&threadm=mailman.6323.1100306430.5135.python-list%40python.org&prev=/groups%3Fhl%3Den%26lr%3D%26group%3Dcomp.lang.python&gt;

**) The traceback from on Oct 31 is also at

<http://lists.wxwidgets.org/cgi-bin/ezmlm-cgi?11:msp:33432:leapomhlkkagbceihodl&gt;

Jean Brouwers wrote:

About two months ago, we exchanged a couple of posts about handling interrupt in a wxPython application. In the mean time, we have done a little more work on this issue and the results are below.

We copied the clearSigInt code from wx.App.__init__ in 2.5.x to our App.OnInit() method and tried different cases as indicate by the numbered comments below.

class App(wx.App):
   ....
   def OnInit(self):
        # copied from wx.App.__init__() in wxPython 2.5.x
        # file wxPythonSrc-2.5,x/wxPython/src/_app_ex.py
       if True: # clearSigInt:
           try:
               import signal
#1 signal.signal(signal.SIGINT, signal.SIG_DFL) # behaves as expected
#2 signal.signal(signal.SIGINT, signal.SIG_IGN) # surprise, Ctrl-C does interrupt
#3 signal.signal(signal.SIGINT, signal.default_int_handler) # crashes on Ctrl+C
           except:
               pass

It turns out that both cases #1 and #2 behave exactly the same as the default behavior in wxPython 2.4.1.2: hitting Ctrl+C in the terminal window interrupts the application, always. This is unexpected for case #2, since Ctrl+C should have no effect.

However, case #3 crashes the application with a segmentation fault after Ctrl+C is typed in the terminal window. Attached is the traceback from the core file and it does appear that there is a problem in Python. But it does not seem to be related to SIG_DFL being zero, as far as we can tell.

In addition, printing the value returned by the signal.signal() call does not show anything, not 0, not 1, nothing. It looks like an empty string but repr() does not show anything either.

We are not sure what to make of this and hope this might be helpful to you.

/Jean Brouwers
ProphICy Semiconductor, Inc.

PS) This is wxPython 2.4.1.2 and Python 2.3 on RedHat Linux 8 with GTK2.

Robin Dunn wrote:

Jean Brouwers wrote:

What about this surprise?

Test #1

$ python
Python 2.3 (#3, Jul 30 2003, 15:13:26)
[GCC 3.2 20020903 (Red Hat Linux 8.0 3.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.getsignal(signal.SIGINT)
<built-in function default_int_handler> # as expected
>>> import wx
>>> signal.getsignal(signal.SIGINT)
Segmentation fault (core dumped) # wow!

Yep. This is a bug in Python. wx.App.__init__ sets the signal handler to SIG_DFL (which is zero in C) and then when you call getsignal Python tries to turn the pointer it gets (NULL) into a PyObject to return. It would normally be some callable python object, but in this case Python ends up dereferencing a NULL pointer and crashing.

I'm pretty sure I entered this into the Python bug tracker, or found it there already, although I can't find it right now. If you have time you might try looking for it and entering it again if not found so it can be fixed before 2.4.

------------------------------------------------------------------------

Traceback of the segmentation fault after Ctrl+C when restoring the default SIGINT
handler with signal.signal(signal.SIG_INT, signal.default_int_handler) in the OnInit()
method of the main App(wx.App) class of a Python 2.3 and wxPython 2.4.1.2 application.

/Jean Brouwers
ProphICy Semiconductor, Inc.

[ProphICy ~/src]$ gdb /ProphICy/bin/python core.23994
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...

warning: core file may not match specified executable file.
Core was generated by `/ProphICy/bin/python runGui.py ..'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/i686/libpthread.so.0...done.
Loaded symbols for /lib/i686/libpthread.so.0
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libutil.so.1...done.
Loaded symbols for /lib/libutil.so.1
Reading symbols from /usr/lib/libstdc++.so.5...done.
Loaded symbols for /usr/lib/libstdc++.so.5
Reading symbols from /lib/i686/libm.so.6...done.
Loaded symbols for /lib/i686/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/strop.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/strop.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/time.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/time.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cStringIO.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cStringIO.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/fcntl.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/fcntl.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/select.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/select.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/termios.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/termios.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/resource.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/resource.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_socket.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_socket.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_ssl.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_ssl.so
Reading symbols from /lib/libssl.so.2...done.
Loaded symbols for /lib/libssl.so.2
Reading symbols from /lib/libcrypto.so.2...done.
Loaded symbols for /lib/libcrypto.so.2
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_weakref.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_weakref.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/operator.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/operator.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/math.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/math.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/itertools.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/itertools.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cPickle.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/cPickle.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/wxc.so...done.

Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/wxc.so
Reading symbols from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so...done.
Loaded symbols for /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
Reading symbols from /usr/lib/libgtk-x11-2.0.so.0...done.
Loaded symbols for /usr/lib/libgtk-x11-2.0.so.0
Reading symbols from /usr/lib/libgdk-x11-2.0.so.0...done.
Loaded symbols for /usr/lib/libgdk-x11-2.0.so.0
Reading symbols from /usr/lib/libatk-1.0.so.0...done.
Loaded symbols for /usr/lib/libatk-1.0.so.0
Reading symbols from /usr/lib/libgdk_pixbuf-2.0.so.0...done.
Loaded symbols for /usr/lib/libgdk_pixbuf-2.0.so.0
Reading symbols from /usr/lib/libpangoxft-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangoxft-1.0.so.0
Reading symbols from /usr/lib/libpangox-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangox-1.0.so.0
Reading symbols from /usr/lib/libpango-1.0.so.0...done.
Loaded symbols for /usr/lib/libpango-1.0.so.0
Reading symbols from /usr/lib/libgobject-2.0.so.0...done.
Loaded symbols for /usr/lib/libgobject-2.0.so.0
Reading symbols from /usr/lib/libgmodule-2.0.so.0...done.
Loaded symbols for /usr/lib/libgmodule-2.0.so.0
Reading symbols from /usr/lib/libgthread-2.0.so.0...done.
Loaded symbols for /usr/lib/libgthread-2.0.so.0
Reading symbols from /usr/lib/libglib-2.0.so.0...done.
Loaded symbols for /usr/lib/libglib-2.0.so.0
Reading symbols from /usr/lib/libpangoft2-1.0.so.0...done.
Loaded symbols for /usr/lib/libpangoft2-1.0.so.0
Reading symbols from /usr/X11R6/lib/libXi.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXi.so.6
Reading symbols from /usr/X11R6/lib/libXext.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXext.so.6
Reading symbols from /usr/lib/libXft.so.2...done.
Loaded symbols for /usr/lib/libXft.so.2
Reading symbols from /usr/X11R6/lib/libXrender.so.1...done.
Loaded symbols for /usr/X11R6/lib/libXrender.so.1
Reading symbols from /usr/lib/libfontconfig.so.1...done.
Loaded symbols for /usr/lib/libfontconfig.so.1
Reading symbols from /usr/X11R6/lib/libX11.so.6...done.
Loaded symbols for /usr/X11R6/lib/libX11.so.6
Reading symbols from /usr/lib/libfreetype.so.6...done.
Loaded symbols for /usr/lib/libfreetype.so.6
Reading symbols from /usr/lib/libexpat.so.0...done.
Loaded symbols for /usr/lib/libexpat.so.0
Reading symbols from /usr/X11R6/lib/X11/locale/common/xlcUTF8Load.so.2...done.
Loaded symbols for /usr/X11R6/lib/X11/locale/common/xlcUTF8Load.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /usr/lib/gtk-2.0/2.0.0/engines/libbluecurve.so...done.
Loaded symbols for /usr/lib/gtk-2.0/2.0.0/engines/libbluecurve.so
Reading symbols from /usr/lib/gconv/ISO8859-1.so...done.
Loaded symbols for /usr/lib/gconv/ISO8859-1.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_locale.so...done.
Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/lib-dynload/_locale.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/htmlc.so...done.

Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/htmlc.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/gridc.so...done.

Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/gridc.so
Reading symbols from /usr/lib/pango/1.1.0/modules/pango-basic-xft.so...done.
Loaded symbols for /usr/lib/pango/1.1.0/modules/pango-basic-xft.so
Reading symbols from /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/stc_c.so...done.

Loaded symbols for /ProphICy/tools/python2.3/lib/python2.3/site-packages/wxPython/stc_c.so
#0 PyEval_EvalCodeEx (co=0x406a3ae0, globals=0x835b3d0, locals=0x0, args=0x4166c1d8, argcount=2,
   kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2493
2493 Py_INCREF(x);

(gdb) backtrace
#0 PyEval_EvalCodeEx (co=0x406a3ae0, globals=0x835b3d0, locals=0x0, args=0x4166c1d8, argcount=2,
   kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2493
#1 0x080ec871 in function_call (func=0x41808ca4, arg=0x4166c1cc, kw=0x0) at Objects/funcobject.c:504
#2 0x0805b058 in PyObject_Call (func=0x0, arg=0x4166c1cc, kw=0x0) at Objects/abstract.c:1755
#3 0x080610f0 in instancemethod_call (func=0x41808ca4, arg=0x4166c1cc, kw=0x0)
   at Objects/classobject.c:2432
#4 0x0805b058 in PyObject_Call (func=0x0, arg=0x406a136c, kw=0x0) at Objects/abstract.c:1755
#5 0x080a4307 in PyEval_CallObjectWithKeywords (func=0x418037d4, arg=0x406a136c, kw=0x0)
   at Python/ceval.c:3346
#6 0x40825cc7 in wxPyCallback::EventThunker(wxEvent&) (this=0x841a4d0, event=@0x406a136c)
   at src/helpers.cpp:1246
#7 0x40cc23b2 in wxEvtHandler::SearchDynamicEventTable(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#8 0x40cc1e99 in wxEvtHandler::ProcessEvent(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#9 0x40c2cc52 in wxApp::SendIdleEvents(wxWindow*) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#10 0x40c2cb90 in wxApp::SendIdleEvents() ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#11 0x40c2cb3f in wxApp::OnIdle(wxIdleEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#12 0x40cc212a in wxEvtHandler::SearchEventTable(wxEventTable&, wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#13 0x40cc1edb in wxEvtHandler::ProcessEvent(wxEvent&) ()
  from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#14 0x40c2cab1 in wxApp::ProcessIdle() () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#15 0x40c2c3af in wxapp_idle_callback () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#16 0x412f2c83 in g_idle_dispatch () from /usr/lib/libglib-2.0.so.0
#17 0x412eff65 in g_main_dispatch () from /usr/lib/libglib-2.0.so.0
#18 0x412f0f98 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#19 0x412f12ad in g_main_context_iterate () from /usr/lib/libglib-2.0.so.0
#20 0x412f1a1f in g_main_loop_run () from /usr/lib/libglib-2.0.so.0
#21 0x4102939f in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#22 0x40c2cce2 in wxApp::MainLoop() () from /ProphICy/tools/wxPython2.4.1.2/lib/libwx_gtk2d-2.4.so
#23 0x40822f23 in wxPyApp::MainLoop() (this=0x83fc1b0) at src/helpers.cpp:131
#24 0x4082c546 in _wrap_wxPyApp_MainLoop (self=0x0, args=0x406a134c, kwargs=0x406a2714)
   at src/gtk/wx.cpp:1383
#25 0x080ecc78 in PyCFunction_Call (func=0x4069ea0c, arg=0x406a134c, kw=0x2)
   at Objects/methodobject.c:108
#26 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a134c, kw=0x406a2714)
   at Objects/abstract.c:1755
#27 0x080a49d9 in ext_do_call (func=0x4069ea0c, pp_stack=0xbfffd07c, flags=1, na=1, nk=0)
   at Python/ceval.c:3713
#28 0x080a2e76 in eval_frame (f=0x8229c6c) at Python/ceval.c:2151
#29 0x080a357a in PyEval_EvalCodeEx (co=0x4062fda0, globals=0x406a134c, locals=0x0, args=0x406a1318,
   argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2663
#30 0x080ec871 in function_call (func=0x4164f1ec, arg=0x406a130c, kw=0x0) at Objects/funcobject.c:504
#31 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a130c, kw=0x0) at Objects/abstract.c:1755
#32 0x080610f0 in instancemethod_call (func=0x4164f1ec, arg=0x406a130c, kw=0x0)
   at Objects/classobject.c:2432
#33 0x0805b058 in PyObject_Call (func=0x822f8d8, arg=0x406a130c, kw=0x0) at Objects/abstract.c:1755
#34 0x080a4743 in do_call (func=0x417ed93c, pp_stack=0xbfffd4ac, na=1, nk=1080693516)
   at Python/ceval.c:3644
#35 0x080a43ef in call_function (pp_stack=0xbfffd4ac, oparg=1080693516) at Python/ceval.c:3460
#36 0x080a2a48 in eval_frame (f=0x819eca4) at Python/ceval.c:2116
#37 0x080a467d in fast_function (func=0x2, pp_stack=0xbfffd5dc, n=1, na=1, nk=0)
   at Python/ceval.c:3518
#38 0x080a445f in call_function (pp_stack=0xbfffd5dc, oparg=1080693516) at Python/ceval.c:3458
#39 0x080a2a48 in eval_frame (f=0x815a9a4) at Python/ceval.c:2116
#40 0x080a357a in PyEval_EvalCodeEx (co=0x4042ce20, globals=0x406a130c, locals=0x0, args=0x815aaf0,
   argcount=1, kws=0x81939d4, kwcount=1, defs=0x404d96f8, defcount=1, closure=0x0)
   at Python/ceval.c:2663
#41 0x080a4601 in fast_function (func=0x2, pp_stack=0xbfffd77c, n=3, na=1, nk=135870932)
   at Python/ceval.c:3529
#42 0x080a445f in call_function (pp_stack=0xbfffd77c, oparg=1080693516) at Python/ceval.c:3458
#43 0x080a2a48 in eval_frame (f=0x819386c) at Python/ceval.c:2116
#44 0x080a467d in fast_function (func=0x2, pp_stack=0xbfffd8ac, n=0, na=0, nk=0)
   at Python/ceval.c:3518
#45 0x080a445f in call_function (pp_stack=0xbfffd8ac, oparg=1080693516) at Python/ceval.c:3458
#46 0x080a2a48 in eval_frame (f=0x812ac7c) at Python/ceval.c:2116
#47 0x080a357a in PyEval_EvalCodeEx (co=0x40196760, globals=0x406a130c, locals=0x4016f79c, args=0x0,
   argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2663
#48 0x080a5b06 in PyEval_EvalCode (co=0x40196760, globals=0x4016f79c, locals=0x4016f79c)
   at Python/ceval.c:537
#49 0x080caee9 in run_node (n=0x40158338, filename=0xbffff76a "runGui.py", globals=0x4016f79c,
   locals=0x4016f79c, flags=0xbfffda08) at Python/pythonrun.c:1205
#50 0x080ca795 in PyRun_SimpleFileExFlags (fp=0x8128b28, filename=0xbffff76a "runGui.py", closeit=1,
   flags=0xbfffda08) at Python/pythonrun.c:802
#51 0x08054c6e in Py_Main (argc=0, argv=0xbfffda84) at Modules/main.c:415
#52 0x080547e7 in main (argc=4, argv=0xbfffda84) at Modules/python.c:23
#53 0x420158f7 in __libc_start_main () from /lib/i686/libc.so.6
(gdb) quit

------------------------------------------------------------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Jean Brouwers wrote:

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Does the exception happen when you set SIGINT or when you press Ctrl-C?

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError.

IIRC, I think that the TypeError is because the signal extension module is mixing types. It is taking the current handler and returning it as if it was a Python function, but once you've set IGN or DFL then the value is an integer flag and not a pointer to a function.

Hitting Cltr+C at that time results in a crash, consistently and repeatably.

When you press Ctrl-C or when the app exits? (The segfault at exit was the issue that prompted the signal deactivation changes in the first palce.)

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT.

See above. SIG_IGN and SIG_DFL are integers, but Python is trying to use the return value from signal() as a pointer and doesn't check for SIG_IGN or SIG_DFL. (Unless something has changed since I last traced through that code.)

Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the

You should try updating at least to 2.4.2.4, __wxPreStart was changed by then and doesn't call PyOS_FiniInterrupts().

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin,

Before answering your specific questions, here is a description of what we have been able to accomplish in the mean time. Major progress, but no cigar yet.

In order to minimize the number of changes, we rebuilt wxPython 2.4.1.2 with just the call to PyOS_FiniInterrupt() commented out. That made quite a difference, since signal.signal() calls no longer throw exceptions!

In addition, we do set the signal handler for SIGINT to SIG_IGN right before calling MainLoop(), just like the clearSigInt argument does in wxPython 2.5.x. Plus, before invoking each command in our modified Py Shell, we set the SIGINT handler to the Python default_int_handler. Rigth after the command returns, we set the SIGINT handler back to SIG_IGN.

This allows us to use Ctrl+C to interrupt long running commands, reliably and without crashes. Second major improvement. The only caveat is that Ctrl+C must be entered in the xterm window where the application was started from, but we can live with that.

There are three new issues, however. The first one is that raising an exception from within a wxPython key event handler does not seem to have any effect at all. Some of our commands call a method pending() which in turn calls wx.YieldIfNeeded(). Certain key events like Ctrl+D set a flag and the pending() method throws the KeyboardInterrupt if that flag is set. However, that KeyboardInterrupt exception does not terminate the original command which called pending(). It seems that the exception is caught by the wxPython event manager or maybe by wx.YieldIfNeeded() and never gets raised past that point.

The second problem is that using Ctrl+C while checking for pending() interrupts has no effect either. Note, the signal handler for SIGINT is the default_int_handler and not SIG_IGN! But typing Ctrl+C does nothing inside wx.YieldIfNeeded(), the key event handler for Ctrl+C is never called. But the key event handler for Cltr+D or other keys is.

As a result, we need to have two different keys to interrupt commands: Ctrl+C in the xterm window and Cltr+D in the wxPython window. We can live with that too, but it would be better if that were just a single Cltr+C key stroke.

Finally, the third issue is that we tried to use the GTK option '--g-fatal-warnnings' to determine where certain GTK warnings originate from. That particular option causes GTK to call abort() when it prints a 'fatal warning' message. We install a Python signal handler to catch the SIGABRT signal and that part works fine now. But after GTK prints the warning and calls abort(), our handler in Python is not called. Instead, the application crashes with a core dump. This is not a show stopper at this moment, but it indicates that there is still an issue with calling Python signal handlers**.

In summary, removing the call to PyOS_FiniInterrupt() is major progress. There are still other improvements to be made, but we do have a workable, albeit slightly clumsy system at this moment.

/Jean Brouwers
ProphICy Semiconductor, Inc.

**) Our take is that wxPython doesn't allow Python to do its normal signal handling routine, but we may be wrong on that. Same diclaimer as before.

Python handles signals in a special, 'synchronous' fashion. A lower level signal handler in C just marks that a signal did occur (was tripped), unless the signal is ignored or handled by default. Then, at some later time, Python C function PyErr_CheckSignals() is called and it calls the Python handlers installed for any tripped signals. The doc is here

<http://www.gmu.edu/mlnavbar/webdev/doc-python/api/exceptionHandling.html&gt;

We grep'ed all wxPython source code and there is nowhere any call to PyErr_CheckSignals() and we believe that that will be necessary. It would be possible to call PyErr_CheckSignals() somewhere in our code, like at the end of a command. But that requires an extension of the Python signal module or better a wxPython provided interface the PyErr_CheckSignals() function. Amybe wxPython should handle this directly, like other packages do. Two examples are

<http://mail.python.org/pipermail/patches/2003-November/013771.html&gt;

and

<Python download | SourceForge.net;

Robin Dunn wrote:

···

Jean Brouwers wrote:

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Does the exception happen when you set SIGINT or when you press Ctrl-C?

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError.

IIRC, I think that the TypeError is because the signal extension module is mixing types. It is taking the current handler and returning it as if it was a Python function, but once you've set IGN or DFL then the value is an integer flag and not a pointer to a function.

Hitting Cltr+C at that time results in a crash, consistently and repeatably.

When you press Ctrl-C or when the app exits? (The segfault at exit was the issue that prompted the signal deactivation changes in the first palce.)

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT.

See above. SIG_IGN and SIG_DFL are integers, but Python is trying to use the return value from signal() as a pointer and doesn't check for SIG_IGN or SIG_DFL. (Unless something has changed since I last traced through that code.)

Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the

You should try updating at least to 2.4.2.4, __wxPreStart was changed by then and doesn't call PyOS_FiniInterrupts().

Okay, I think that there are actually two separate issues here. Catching signals, and the sometimes missing KeyboardInterrupt.

So to figure out what is going on with the signals I hacked up the simple sample (attached) and played around with it. This was done in my current CVS worksapce (2.5.3.x) with a wxGTK2 unicode build. I first experimented with SIGUSR1 just to completly avoid the SIGINT/KeyboardInterrupt issues. As I expected I found that:

* Sending the signal within the same with os.kill(pid, SIGUSR1) shows the signal handler being called (seemingly) immediately.

* Sending the signal for outside the app with "kill -USR1 pid" command shows that the handler is not called immediatly, but only after some python code executes in an another event handler, (such as clicking the Just for Fun button in this example.) This is because when the signal happens Python doesn't call the handler immediately, but just schedules it to be called later in between atomic python opcodes.

* Adding a timer to the app to ensure that there are some Python opcodes executing fairly often allows the external signal to be handled fairly quickly after it happens.

The main reason I did this was to determine if I should be calling PyErr_CheckSignals after every event handler, or perhaps after every method call. I noticed that the patch you referenced hasn't been applied to Python after a coupel years, and it is only called very sparingly from within Python itself, so I was concerned about possible implications of doing it so often from wxPython. But it appears to me to not be needed because in either of those cases (events or method calls) there will be some Python opcodes executed either just before or just after anyway so we can let Python take care of the signals itself. The only thing that could help is to call PyErr_CheckSignals from within a custom wx.App.MainLoop, but I think that may cause more troubles than it solves, especially since it can be solved just by adding a timer to the app like I did.

Okay, now on to SIGINT. I added a custom handler for it just like I did with SIGUSR1 and found that it worked exactly like SIGUSR1, as expected. I then added a "raise KeyboardInterrupt" to the handler to make it equivallent to default_int_handler. Here are my findings:

* Sending the signal from the same app with os.kill(pid, SIGINT) will allow the exception to be raised back to the event handler that did the kill. It then gets printed upon returning from the event handler to the C++ wrapper code where I do a PyErr_Print(); Based on the results above this was expected since there is nothing but Python code between the sending of the signal to the catching of the exception.

* Sending the signal externally (with the timer still in place) shows that the signal is being caught and the handler is called, but the exception is getting lost. This is undoubtedly due to my calling PyErr_Clear in various places in wxPython and is probably the root of the problem from your perspective.

Unfortunatly some of those PyErr_Clear's are needed because some things that the wxPython wrappers do internally will cause an exception upon errors, but I then handle the error myself so I clear it. I'll look furhter into it though to see if some of the PyErr_Clear's can be removed and if there is some way around the others...

More comments below:

Jean Brouwers wrote:

Robin,

Before answering your specific questions, here is a description of what we have been able to accomplish in the mean time. Major progress, but no cigar yet.

In order to minimize the number of changes, we rebuilt wxPython 2.4.1.2 with just the call to PyOS_FiniInterrupt() commented out. That made quite a difference, since signal.signal() calls no longer throw exceptions!

In addition, we do set the signal handler for SIGINT to SIG_IGN right before calling MainLoop(), just like the clearSigInt argument does in wxPython 2.5.x. Plus, before invoking each command in our modified Py Shell, we set the SIGINT handler to the Python default_int_handler. Rigth after the command returns, we set the SIGINT handler back to SIG_IGN.

This allows us to use Ctrl+C to interrupt long running commands, reliably and without crashes. Second major improvement. The only caveat is that Ctrl+C must be entered in the xterm window where the application was started from, but we can live with that.

There are three new issues, however. The first one is that raising an exception from within a wxPython key event handler does not seem to have any effect at all. Some of our commands call a method pending() which in turn calls wx.YieldIfNeeded(). Certain key events like Ctrl+D set a flag and the pending() method throws the KeyboardInterrupt if that flag is set. However, that KeyboardInterrupt exception does not terminate the original command which called pending(). It seems that the exception is caught by the wxPython event manager or maybe by wx.YieldIfNeeded() and never gets raised past that point.

After every call to an event handler or other callback wxPython does a PyErr_Print call which prints the traceback and clears the error. This is done because there is not an easy way to propogate the exception past the C++ layer back up to the previous Python layer. This has been discussed in the past as the Python/C++ sandwhich, which is basically alternating layers of Python and C++ code on the stack. There probably are ways to do it with C++ exceptiuons but it will increase the complexity of the wrappers by probably an order of magnitude, and wxWidgets probably still isn't fully exception safe.

The second problem is that using Ctrl+C while checking for pending() interrupts has no effect either. Note, the signal handler for SIGINT is the default_int_handler and not SIG_IGN! But typing Ctrl+C does nothing inside wx.YieldIfNeeded(), the key event handler for Ctrl+C is never called. But the key event handler for Cltr+D or other keys is.

As a result, we need to have two different keys to interrupt commands: Ctrl+C in the xterm window and Cltr+D in the wxPython window. We can live with that too, but it would be better if that were just a single Cltr+C key stroke.

Finally, the third issue is that we tried to use the GTK option '--g-fatal-warnnings' to determine where certain GTK warnings originate from. That particular option causes GTK to call abort() when it prints a 'fatal warning' message. We install a Python signal handler to catch the SIGABRT signal and that part works fine now. But after GTK prints the warning and calls abort(), our handler in Python is not called. Instead, the application crashes with a core dump. This is not a show stopper at this moment, but it indicates that there is still an issue with calling Python signal handlers**.

Read the man page for abort(). It says that the abort() function causes abnormal program termination unless the signal SIGABRT is caught and the signal handler does not return. The Python C function used to catch the signals and to set things up to invoke the handler funciton later *always* returns and so abort() will *always* cause the app to terminate and to dump a core file.

In summary, removing the call to PyOS_FiniInterrupt() is major progress. There are still other improvements to be made, but we do have a workable, albeit slightly clumsy system at this moment.

I had an idea on a separate approach that you could take that might be smoother for you.if you had a separate app that was just a button, (or perhaps a taskbar icon) that is spawned by your main app, then it would have it's own event loop and would not get blocked by long running things in the main app. When that button is activated it can send a signal to the parent app with os.kill, and the handler in the parent can do whatever is needed to interrupt the long running thing.

Just a thought.

···

/Jean Brouwers
ProphICy Semiconductor, Inc.

**) Our take is that wxPython doesn't allow Python to do its normal signal handling routine, but we may be wrong on that. Same diclaimer as before. Python handles signals in a special, 'synchronous' fashion. A lower level signal handler in C just marks that a signal did occur (was tripped), unless the signal is ignored or handled by default. Then, at some later time, Python C function PyErr_CheckSignals() is called and it calls the Python handlers installed for any tripped signals. The doc is here

<http://www.gmu.edu/mlnavbar/webdev/doc-python/api/exceptionHandling.html&gt;

We grep'ed all wxPython source code and there is nowhere any call to PyErr_CheckSignals() and we believe that that will be necessary. It would be possible to call PyErr_CheckSignals() somewhere in our code, like at the end of a command. But that requires an extension of the Python signal module or better a wxPython provided interface the PyErr_CheckSignals() function. Amybe wxPython should handle this directly, like other packages do. Two examples are

<http://mail.python.org/pipermail/patches/2003-November/013771.html&gt;

and

<Python download | SourceForge.net;

Robin Dunn wrote:

Jean Brouwers wrote:

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Does the exception happen when you set SIGINT or when you press Ctrl-C?

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError.

IIRC, I think that the TypeError is because the signal extension module is mixing types. It is taking the current handler and returning it as if it was a Python function, but once you've set IGN or DFL then the value is an integer flag and not a pointer to a function.

Hitting Cltr+C at that time results in a crash, consistently and repeatably.

When you press Ctrl-C or when the app exits? (The segfault at exit was the issue that prompted the signal deactivation changes in the first palce.)

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT.

See above. SIG_IGN and SIG_DFL are integers, but Python is trying to use the return value from signal() as a pointer and doesn't check for SIG_IGN or SIG_DFL. (Unless something has changed since I last traced through that code.)

Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the

You should try updating at least to 2.4.2.4, __wxPreStart was changed by then and doesn't call PyOS_FiniInterrupts().

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin,

We did some additional tests, for example adding a call to PyErr_CheckSignals() in the wx.YieldIfNeeded() code but that did not seem make any difference.

Using 'os.kill(os.getpid(), signal.SIGINT)' does not seem to work any better than 'raise KeyboardInterrupt'. Both fail to generate a Python exception from within, not from inside our pending() method nor from inside the key event handler, The os.kill() call will probably trip the signal and Python records that at the lowest level in C. But it looks like the call to the default_int_handler() is never made.

Before making further comments, we would like to try your example and see if we can reproduce the problem. Maybe there is a bug somewhere else in our code.

The example was not attached. Could you please post that again?

/Jean Brouwers
ProphICy Semiconductor, Inc.

Robin Dunn wrote:

···

Okay, I think that there are actually two separate issues here. Catching signals, and the sometimes missing KeyboardInterrupt.

So to figure out what is going on with the signals I hacked up the simple sample (attached) and played around with it. This was done in my current CVS worksapce (2.5.3.x) with a wxGTK2 unicode build. I first experimented with SIGUSR1 just to completly avoid the SIGINT/KeyboardInterrupt issues. As I expected I found that:

* Sending the signal within the same with os.kill(pid, SIGUSR1) shows the signal handler being called (seemingly) immediately.

* Sending the signal for outside the app with "kill -USR1 pid" command shows that the handler is not called immediatly, but only after some python code executes in an another event handler, (such as clicking the Just for Fun button in this example.) This is because when the signal happens Python doesn't call the handler immediately, but just schedules it to be called later in between atomic python opcodes.

* Adding a timer to the app to ensure that there are some Python opcodes executing fairly often allows the external signal to be handled fairly quickly after it happens.

The main reason I did this was to determine if I should be calling PyErr_CheckSignals after every event handler, or perhaps after every method call. I noticed that the patch you referenced hasn't been applied to Python after a coupel years, and it is only called very sparingly from within Python itself, so I was concerned about possible implications of doing it so often from wxPython. But it appears to me to not be needed because in either of those cases (events or method calls) there will be some Python opcodes executed either just before or just after anyway so we can let Python take care of the signals itself. The only thing that could help is to call PyErr_CheckSignals from within a custom wx.App.MainLoop, but I think that may cause more troubles than it solves, especially since it can be solved just by adding a timer to the app like I did.

Okay, now on to SIGINT. I added a custom handler for it just like I did with SIGUSR1 and found that it worked exactly like SIGUSR1, as expected. I then added a "raise KeyboardInterrupt" to the handler to make it equivallent to default_int_handler. Here are my findings:

* Sending the signal from the same app with os.kill(pid, SIGINT) will allow the exception to be raised back to the event handler that did the kill. It then gets printed upon returning from the event handler to the C++ wrapper code where I do a PyErr_Print(); Based on the results above this was expected since there is nothing but Python code between the sending of the signal to the catching of the exception.

* Sending the signal externally (with the timer still in place) shows that the signal is being caught and the handler is called, but the exception is getting lost. This is undoubtedly due to my calling PyErr_Clear in various places in wxPython and is probably the root of the problem from your perspective.

Unfortunatly some of those PyErr_Clear's are needed because some things that the wxPython wrappers do internally will cause an exception upon errors, but I then handle the error myself so I clear it. I'll look furhter into it though to see if some of the PyErr_Clear's can be removed and if there is some way around the others...

More comments below:

Jean Brouwers wrote:

Robin,

Before answering your specific questions, here is a description of what we have been able to accomplish in the mean time. Major progress, but no cigar yet.

In order to minimize the number of changes, we rebuilt wxPython 2.4.1.2 with just the call to PyOS_FiniInterrupt() commented out. That made quite a difference, since signal.signal() calls no longer throw exceptions!

In addition, we do set the signal handler for SIGINT to SIG_IGN right before calling MainLoop(), just like the clearSigInt argument does in wxPython 2.5.x. Plus, before invoking each command in our modified Py Shell, we set the SIGINT handler to the Python default_int_handler. Rigth after the command returns, we set the SIGINT handler back to SIG_IGN.

This allows us to use Ctrl+C to interrupt long running commands, reliably and without crashes. Second major improvement. The only caveat is that Ctrl+C must be entered in the xterm window where the application was started from, but we can live with that.

There are three new issues, however. The first one is that raising an exception from within a wxPython key event handler does not seem to have any effect at all. Some of our commands call a method pending() which in turn calls wx.YieldIfNeeded(). Certain key events like Ctrl+D set a flag and the pending() method throws the KeyboardInterrupt if that flag is set. However, that KeyboardInterrupt exception does not terminate the original command which called pending(). It seems that the exception is caught by the wxPython event manager or maybe by wx.YieldIfNeeded() and never gets raised past that point.

After every call to an event handler or other callback wxPython does a PyErr_Print call which prints the traceback and clears the error. This is done because there is not an easy way to propogate the exception past the C++ layer back up to the previous Python layer. This has been discussed in the past as the Python/C++ sandwhich, which is basically alternating layers of Python and C++ code on the stack. There probably are ways to do it with C++ exceptiuons but it will increase the complexity of the wrappers by probably an order of magnitude, and wxWidgets probably still isn't fully exception safe.

The second problem is that using Ctrl+C while checking for pending() interrupts has no effect either. Note, the signal handler for SIGINT is the default_int_handler and not SIG_IGN! But typing Ctrl+C does nothing inside wx.YieldIfNeeded(), the key event handler for Ctrl+C is never called. But the key event handler for Cltr+D or other keys is.

As a result, we need to have two different keys to interrupt commands: Ctrl+C in the xterm window and Cltr+D in the wxPython window. We can live with that too, but it would be better if that were just a single Cltr+C key stroke.

Finally, the third issue is that we tried to use the GTK option '--g-fatal-warnnings' to determine where certain GTK warnings originate from. That particular option causes GTK to call abort() when it prints a 'fatal warning' message. We install a Python signal handler to catch the SIGABRT signal and that part works fine now. But after GTK prints the warning and calls abort(), our handler in Python is not called. Instead, the application crashes with a core dump. This is not a show stopper at this moment, but it indicates that there is still an issue with calling Python signal handlers**.

Read the man page for abort(). It says that the abort() function causes abnormal program termination unless the signal SIGABRT is caught and the signal handler does not return. The Python C function used to catch the signals and to set things up to invoke the handler funciton later *always* returns and so abort() will *always* cause the app to terminate and to dump a core file.

In summary, removing the call to PyOS_FiniInterrupt() is major progress. There are still other improvements to be made, but we do have a workable, albeit slightly clumsy system at this moment.

I had an idea on a separate approach that you could take that might be smoother for you.if you had a separate app that was just a button, (or perhaps a taskbar icon) that is spawned by your main app, then it would have it's own event loop and would not get blocked by long running things in the main app. When that button is activated it can send a signal to the parent app with os.kill, and the handler in the parent can do whatever is needed to interrupt the long running thing.

Just a thought.

/Jean Brouwers
ProphICy Semiconductor, Inc.

**) Our take is that wxPython doesn't allow Python to do its normal signal handling routine, but we may be wrong on that. Same diclaimer as before. Python handles signals in a special, 'synchronous' fashion. A lower level signal handler in C just marks that a signal did occur (was tripped), unless the signal is ignored or handled by default. Then, at some later time, Python C function PyErr_CheckSignals() is called and it calls the Python handlers installed for any tripped signals. The doc is here

<http://www.gmu.edu/mlnavbar/webdev/doc-python/api/exceptionHandling.html&gt;

We grep'ed all wxPython source code and there is nowhere any call to PyErr_CheckSignals() and we believe that that will be necessary. It would be possible to call PyErr_CheckSignals() somewhere in our code, like at the end of a command. But that requires an extension of the Python signal module or better a wxPython provided interface the PyErr_CheckSignals() function. Amybe wxPython should handle this directly, like other packages do. Two examples are

<http://mail.python.org/pipermail/patches/2003-November/013771.html&gt;

and

<Python download | SourceForge.net;

Robin Dunn wrote:

Jean Brouwers wrote:

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Does the exception happen when you set SIGINT or when you press Ctrl-C?

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError.

IIRC, I think that the TypeError is because the signal extension module is mixing types. It is taking the current handler and returning it as if it was a Python function, but once you've set IGN or DFL then the value is an integer flag and not a pointer to a function.

Hitting Cltr+C at that time results in a crash, consistently and repeatably.

When you press Ctrl-C or when the app exits? (The segfault at exit was the issue that prompted the signal deactivation changes in the first palce.)

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT.

See above. SIG_IGN and SIG_DFL are integers, but Python is trying to use the return value from signal() as a pointer and doesn't check for SIG_IGN or SIG_DFL. (Unless something has changed since I last traced through that code.)

Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the

You should try updating at least to 2.4.2.4, __wxPreStart was changed by then and doesn't call PyOS_FiniInterrupts().

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Jean Brouwers wrote:

The example was not attached. Could you please post that again?

Oops, sorry.

signal_test.py (3.56 KB)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin,

After making a few changes, your signal_test program worked as expected on our wxPython2.4.1.2** build.

Attached is a copy of signal_test2 program, extended with a typical call sequence from our application.

We added a button 'Test loop' to simulate a long running command. Clicking the 'Signal SIGINT' button while the test loop is running should break the loop. The SIGINT signal is caught and the KeyboardInterrupt exception is thrown but the exception gets lost and the loop always runs till the end.

That is the main issue.

/Jean Brouwers
ProphICy Semiconductor, Inc.

**) This is wxPython2.4.1.2 with the PyOS_FiniInterrupt() call commented out and Python 2.3.3 on RedHat Linux 8 with GTK2 and without Unicode.

Jean Brouwers wrote:

signal_test2.py (7.52 KB)

···

Robin,

We did some additional tests, for example adding a call to PyErr_CheckSignals() in the wx.YieldIfNeeded() code but that did not seem make any difference.

Using 'os.kill(os.getpid(), signal.SIGINT)' does not seem to work any better than 'raise KeyboardInterrupt'. Both fail to generate a Python exception from within, not from inside our pending() method nor from inside the key event handler, The os.kill() call will probably trip the signal and Python records that at the lowest level in C. But it looks like the call to the default_int_handler() is never made.

Before making further comments, we would like to try your example and see if we can reproduce the problem. Maybe there is a bug somewhere else in our code.

The example was not attached. Could you please post that again?

/Jean Brouwers
ProphICy Semiconductor, Inc.

Robin Dunn wrote:

Okay, I think that there are actually two separate issues here. Catching signals, and the sometimes missing KeyboardInterrupt.

So to figure out what is going on with the signals I hacked up the simple sample (attached) and played around with it. This was done in my current CVS worksapce (2.5.3.x) with a wxGTK2 unicode build. I first experimented with SIGUSR1 just to completly avoid the SIGINT/KeyboardInterrupt issues. As I expected I found that:

* Sending the signal within the same with os.kill(pid, SIGUSR1) shows the signal handler being called (seemingly) immediately.

* Sending the signal for outside the app with "kill -USR1 pid" command shows that the handler is not called immediatly, but only after some python code executes in an another event handler, (such as clicking the Just for Fun button in this example.) This is because when the signal happens Python doesn't call the handler immediately, but just schedules it to be called later in between atomic python opcodes.

* Adding a timer to the app to ensure that there are some Python opcodes executing fairly often allows the external signal to be handled fairly quickly after it happens.

The main reason I did this was to determine if I should be calling PyErr_CheckSignals after every event handler, or perhaps after every method call. I noticed that the patch you referenced hasn't been applied to Python after a coupel years, and it is only called very sparingly from within Python itself, so I was concerned about possible implications of doing it so often from wxPython. But it appears to me to not be needed because in either of those cases (events or method calls) there will be some Python opcodes executed either just before or just after anyway so we can let Python take care of the signals itself. The only thing that could help is to call PyErr_CheckSignals from within a custom wx.App.MainLoop, but I think that may cause more troubles than it solves, especially since it can be solved just by adding a timer to the app like I did.

Okay, now on to SIGINT. I added a custom handler for it just like I did with SIGUSR1 and found that it worked exactly like SIGUSR1, as expected. I then added a "raise KeyboardInterrupt" to the handler to make it equivallent to default_int_handler. Here are my findings:

* Sending the signal from the same app with os.kill(pid, SIGINT) will allow the exception to be raised back to the event handler that did the kill. It then gets printed upon returning from the event handler to the C++ wrapper code where I do a PyErr_Print(); Based on the results above this was expected since there is nothing but Python code between the sending of the signal to the catching of the exception.

* Sending the signal externally (with the timer still in place) shows that the signal is being caught and the handler is called, but the exception is getting lost. This is undoubtedly due to my calling PyErr_Clear in various places in wxPython and is probably the root of the problem from your perspective.

Unfortunatly some of those PyErr_Clear's are needed because some things that the wxPython wrappers do internally will cause an exception upon errors, but I then handle the error myself so I clear it. I'll look furhter into it though to see if some of the PyErr_Clear's can be removed and if there is some way around the others...

More comments below:

Jean Brouwers wrote:

Robin,

Before answering your specific questions, here is a description of what we have been able to accomplish in the mean time. Major progress, but no cigar yet.

In order to minimize the number of changes, we rebuilt wxPython 2.4.1.2 with just the call to PyOS_FiniInterrupt() commented out. That made quite a difference, since signal.signal() calls no longer throw exceptions!

In addition, we do set the signal handler for SIGINT to SIG_IGN right before calling MainLoop(), just like the clearSigInt argument does in wxPython 2.5.x. Plus, before invoking each command in our modified Py Shell, we set the SIGINT handler to the Python default_int_handler. Rigth after the command returns, we set the SIGINT handler back to SIG_IGN.

This allows us to use Ctrl+C to interrupt long running commands, reliably and without crashes. Second major improvement. The only caveat is that Ctrl+C must be entered in the xterm window where the application was started from, but we can live with that.

There are three new issues, however. The first one is that raising an exception from within a wxPython key event handler does not seem to have any effect at all. Some of our commands call a method pending() which in turn calls wx.YieldIfNeeded(). Certain key events like Ctrl+D set a flag and the pending() method throws the KeyboardInterrupt if that flag is set. However, that KeyboardInterrupt exception does not terminate the original command which called pending(). It seems that the exception is caught by the wxPython event manager or maybe by wx.YieldIfNeeded() and never gets raised past that point.

After every call to an event handler or other callback wxPython does a PyErr_Print call which prints the traceback and clears the error. This is done because there is not an easy way to propogate the exception past the C++ layer back up to the previous Python layer. This has been discussed in the past as the Python/C++ sandwhich, which is basically alternating layers of Python and C++ code on the stack. There probably are ways to do it with C++ exceptiuons but it will increase the complexity of the wrappers by probably an order of magnitude, and wxWidgets probably still isn't fully exception safe.

The second problem is that using Ctrl+C while checking for pending() interrupts has no effect either. Note, the signal handler for SIGINT is the default_int_handler and not SIG_IGN! But typing Ctrl+C does nothing inside wx.YieldIfNeeded(), the key event handler for Ctrl+C is never called. But the key event handler for Cltr+D or other keys is.

As a result, we need to have two different keys to interrupt commands: Ctrl+C in the xterm window and Cltr+D in the wxPython window. We can live with that too, but it would be better if that were just a single Cltr+C key stroke.

Finally, the third issue is that we tried to use the GTK option '--g-fatal-warnnings' to determine where certain GTK warnings originate from. That particular option causes GTK to call abort() when it prints a 'fatal warning' message. We install a Python signal handler to catch the SIGABRT signal and that part works fine now. But after GTK prints the warning and calls abort(), our handler in Python is not called. Instead, the application crashes with a core dump. This is not a show stopper at this moment, but it indicates that there is still an issue with calling Python signal handlers**.

Read the man page for abort(). It says that the abort() function causes abnormal program termination unless the signal SIGABRT is caught and the signal handler does not return. The Python C function used to catch the signals and to set things up to invoke the handler funciton later *always* returns and so abort() will *always* cause the app to terminate and to dump a core file.

In summary, removing the call to PyOS_FiniInterrupt() is major progress. There are still other improvements to be made, but we do have a workable, albeit slightly clumsy system at this moment.

I had an idea on a separate approach that you could take that might be smoother for you.if you had a separate app that was just a button, (or perhaps a taskbar icon) that is spawned by your main app, then it would have it's own event loop and would not get blocked by long running things in the main app. When that button is activated it can send a signal to the parent app with os.kill, and the handler in the parent can do whatever is needed to interrupt the long running thing.

Just a thought.

/Jean Brouwers
ProphICy Semiconductor, Inc.

**) Our take is that wxPython doesn't allow Python to do its normal signal handling routine, but we may be wrong on that. Same diclaimer as before. Python handles signals in a special, 'synchronous' fashion. A lower level signal handler in C just marks that a signal did occur (was tripped), unless the signal is ignored or handled by default. Then, at some later time, Python C function PyErr_CheckSignals() is called and it calls the Python handlers installed for any tripped signals. The doc is here

<http://www.gmu.edu/mlnavbar/webdev/doc-python/api/exceptionHandling.html&gt;

We grep'ed all wxPython source code and there is nowhere any call to PyErr_CheckSignals() and we believe that that will be necessary. It would be possible to call PyErr_CheckSignals() somewhere in our code, like at the end of a command. But that requires an extension of the Python signal module or better a wxPython provided interface the PyErr_CheckSignals() function. Amybe wxPython should handle this directly, like other packages do. Two examples are

<http://mail.python.org/pipermail/patches/2003-November/013771.html&gt;

and

<Python download | SourceForge.net;

Robin Dunn wrote:

Jean Brouwers wrote:

Robin,

We have been looking further into the crashes on SIGINT and other signals, especially after a recent post from Fernando Perez at comp.lang.python*.

Here is a summary and our conclusions, but with the disclaimer that we have limited understanding of the inner workings of Python and wxPython. This is a serious issue since it not only affects SIGINT but all signals and renders the Python signal module almost useless with wxPython.

After import wxPython, setting the signal handler for SIGINT back to the Python default_int_handler seems to be working. It generates a SystemError exception which is ignored but which should not happen, obviously.

Does the exception happen when you set SIGINT or when you press Ctrl-C?

Setting the signal handler for SIGINT back to SIG_IGN or setting any signal handler to SIG_IGN or SIG_DFL also results in an exception, but a TypeError.

IIRC, I think that the TypeError is because the signal extension module is mixing types. It is taking the current handler and returning it as if it was a Python function, but once you've set IGN or DFL then the value is an integer flag and not a pointer to a function.

Hitting Cltr+C at that time results in a crash, consistently and repeatably.

When you press Ctrl-C or when the app exits? (The segfault at exit was the issue that prompted the signal deactivation changes in the first palce.)

It is unclear what the actual signal handler is for SIGINT and what is causing the TypeError and SystemError, but it is quite clear that both are symptoms of an underlying problem.

The traceback** indicates that the crash occurs at Py_INCR(x) in the Python source file Python/ceval.c on line 2493 in function PyEval_EvalCodeEx(). The value of one of the args is NULL instead of the handler for SIGINT.

See above. SIG_IGN and SIG_DFL are integers, but Python is trying to use the return value from signal() as a pointer and doesn't check for SIG_IGN or SIG_DFL. (Unless something has changed since I last traced through that code.)

Note, this is after the SIGINT handler is reset to SIG_IGN or SIG_DFL.

Also, wxPython function __wxPreStart() in file wxPython/src/helpers.cpp calls Python function PyOS_FiniInterrupts() which is in the

You should try updating at least to 2.4.2.4, __wxPreStart was changed by then and doesn't call PyOS_FiniInterrupts().

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org