[python-win32] SIGSEGV crash at the end of apps using win32uiole / OCX

Robert kxroberto at googlemail.com
Tue Dec 27 17:58:16 CET 2011


This is about a ugly old bug which I dislike for long, which I can 
only suppress by a os._exit() near Python end. Now I found some 
more info. Perhaps somebody sees what it is about?

When a GUI app has ever used a win32uiole OCX like shown in the 
attached minimal example (pythonwin\pywin\Demos\ocx\webbrowser.py, 
just changed to use a standalone frame window), then at the very 
end of the app after all windows have been destroyed and Pythons 
sort of main() with destruction of all Python objects is reached, 
there is a SIGSEGV like shown below in 
python26!PyInterpreterState_Clear ().
Reproduced with various Python 2 versions.


Notes:


* Obviously extra threads are created by the browser OCX if at 
least one .Navigate() occurred.

* if .Navigate() is commented out, and just the Window/OCX 
creations/destructions are done the problem is not. (But then gdb 
doesn't show creation of extra threads. Thus the problem seems to 
have to do with extra threads.)

* "app.Run()" is commented out for a mere standalone run, to 
reproduce the bug easily. Thus the windows are drawn down right 
after creation. If not, then at exit, this (simple) app somehow 
doesn't terminate but seems to wait eternally because of extra IE4 
threads (?). When run with gdb as shown, the hang/eternal wait yet 
is not and the SIGSEGV occurs after .Run() too (!?)

* the problem is not, when the example is run in Pythonwin.exe at 
the end of Pythonwin.exe. The problem is not when such script is 
run with py2exe v0.5.2 stub. (maybe that does rather quickly 
something like os._exit() at the end). But the problem occurs with 
current py2exe 0.6.9 stub, and with all normal python(w).exe's - 
direct start or via interactive sessions.
When Pythonwin is run via python(w).exe and  "import 
pywin.framework.startup ....  app.Run()", and when then the 
webbcrash.py is executed, then after exit of Pythonwin the crash 
is there too. Thus Pythonwin.exe unlike python(w).exe seems to do 
just a sloppy cleanup (like py2exe0.5.2) and thus avoid the problem.

* when os._exit() is done at the end of the script, the problem is 
not existing: the ugly "solution" ;-)
sys.exit() doesn't "solve"  - probably because it doesn't prevent 
against destruction of all Python objects, threads ...

* pywin32 build 216  (but same with 214)

* BTW: if the original pythonwin\pywin\Demos\ocx\webbrowser.py 
(using a MDIClient) is run standalone through python(w).exe, there 
is also a ugly SIGSEGV or even worse C-level crash - now at start. 
It should only raise a Python exception due to the non-working MDI 
setup I guess.




Robert




=========== SIGSEV of webbcrash.py watched with gdb :


SIGSEGV: code "mov 0x4(%ebx),%eax" at 0x1e02e449 points to memory 
0x00000004. cannot read.

C:\scratch>python26 webbcrash.py
Run() ...
Run() terminated.
==> SIGSEGV crash
[uncomment "##app.Run()"]
C:\scratch>gdb python26 webbcrash.py
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show 
copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\bin/python26.exe...(no debugging symbols 
found)...done.
"C:\scratch/webbcrash.py" is not a core dump: File format not 
recognized
(gdb) run
Starting program: C:\bin/python26.exe
          (NOTE: ITS THE SAME WITH C:\Python26\python.exe)
[New Thread 6740.0x10bc]
Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 
bit (Intel)] on2
win32
Type "help", "copyright", "credits" or "license" for more information.
 >>> execfile('webbcrash.py')
Web Browser - http://www.google.com/
[New Thread 6740.0x19d0]
[New Thread 6740.0xdec]
[New Thread 6740.0x1d90]
[New Thread 6740.0x1f00]
[New Thread 6740.0x19cc]
[New Thread 6740.0x26c]
[New Thread 6740.0x118c]
[New Thread 6740.0x153c]
[New Thread 6740.0x1da0]
 >>> exit()

Program received signal SIGSEGV, Segmentation fault.
0x1e02e449 in python26!PyInterpreterState_Clear ()
    from C:\WINDOWS\system32\python26.dll
(gdb) bt
#0  0x1e02e449 in python26!PyInterpreterState_Clear ()
    from C:\WINDOWS\system32\python26.dll
#1  0x00000000 in ?? ()
(gdb) disass
...
    0x1e02e408 <+246>:   call   0x1e02e464 
<python26!PyThread_get_thread_ident>
    0x1e02e40d <+251>:   mov    %eax,0x50(%esi)
    0x1e02e410 <+254>:   mov    %edi,0x40(%esi)
    0x1e02e413 <+257>:   mov    %edi,0x28(%esi)
    0x1e02e416 <+260>:   mov    %edi,0x2c(%esi)
    0x1e02e419 <+263>:   mov    %edi,0x30(%esi)
    0x1e02e41c <+266>:   mov    %edi,0x34(%esi)
    0x1e02e41f <+269>:   mov    %edi,0x38(%esi)
    0x1e02e422 <+272>:   mov    %edi,0x3c(%esi)
    0x1e02e425 <+275>:   mov    %edi,0x18(%esi)
    0x1e02e428 <+278>:   mov    %edi,0x1c(%esi)
    0x1e02e42b <+281>:   mov    %edi,0x20(%esi)
    0x1e02e42e <+284>:   mov    %edi,0x24(%esi)
    0x1e02e431 <+287>:   cmp    %edi,0xc(%esp)
    0x1e02e435 <+291>:   je     0x1e02e43c 
<python26!PyInterpreterState_Clear+298
 >
    0x1e02e437 <+293>:   call   0x1e03111b 
<python26!PyThread_create_key+31>
    0x1e02e43c <+298>:   push   $0x1
    0x1e02e43e <+300>:   pushl  0x1e204f74
    0x1e02e444 <+306>:   call   0x1e02e248 
<python26!PyThread_acquire_lock>
=> 0x1e02e449 <+311>:   mov    0x4(%ebx),%eax
    0x1e02e44c <+314>:   pushl  0x1e204f74
    0x1e02e452 <+320>:   mov    %eax,(%esi)
    0x1e02e454 <+322>:   mov    %esi,0x4(%ebx)
    0x1e02e457 <+325>:   call   0x1e02e2eb 
<python26!PyThread_release_lock>
    0x1e02e45c <+330>:   add    $0xc,%esp
    0x1e02e45f <+333>:   pop    %edi
    0x1e02e460 <+334>:   mov    %esi,%eax
    0x1e02e462 <+336>:   pop    %esi
    0x1e02e463 <+337>:   ret
End of assembler dump.
(gdb)




=========== script to reproduce the crash (attached too)
=== slightly modified pythonwin\pywin\Demos\ocx\webbrowser.py


# This demo uses the IE4 Web Browser control.

# It catches an "OnNavigate" event, and updates the frame title.
# (event stuff by Neil Hodgson)

import win32ui, win32con, win32api, regutil
from pywin.mfc import window, activex
from win32com.client import gencache
import sys, os

WebBrowserModule = 
gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 
1, 1)
if WebBrowserModule is None:
     raise ImportError("IE4 does not appear to be installed.")

class MyWebBrowser(activex.Control, WebBrowserModule.WebBrowser):
     pass
##    def OnBeforeNavigate2(self, pDisp, URL, Flags, 
TargetFrameName, PostData, Headers, Cancel):
##        self.GetParent().OnNavigate(URL)
##        #print "BeforeNavigate2", pDisp, URL, Flags, 
TargetFrameName, PostData, Headers, Cancel

##class BrowserFrame(window.MDIChildWnd):
class BrowserFrame(window.FrameWnd):
     def __init__(self, url = None):
         if url is None:
             self.url = "http://www.google.com"
         else:
             self.url = url
         pass # Dont call base class doc/view version...
     def Create(self, title, rect = None):
         style = win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW
         ##style = win32con.WS_CHILD | win32con.WS_VISIBLE | 
win32con.WS_OVERLAPPEDWINDOW
         ##self._obj_ = win32ui.CreateMDIChild()
         self._obj_ = win32ui.CreateFrame()
         self._obj_.AttachObject(self)
         self._obj_.CreateWindow(None, title, style, rect, self)
         rect = self.GetClientRect()
         rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
         self.ocx = MyWebBrowser()
         self.ocx.CreateControl("Web Browser", win32con.WS_VISIBLE 
| win32con.WS_CHILD, rect, self, 1000)
         self.ocx.Navigate(self.url)
         self.HookMessage (self.OnSize, win32con.WM_SIZE)
     def OnSize (self, params):
         rect = self.GetClientRect()
         rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
         self.ocx.SetWindowPos(0, rect, 0)
     def OnNavigate(self, url):
         title = "Web Browser - %s" % (url,)
         print title
         self.SetWindowText(title)


import pywin.mfc.thread
class MyApp(pywin.mfc.thread.WinApp):
     frame = None
     def InitInstance(self): #$pycheck_no
         global f
         self.frame = f = BrowserFrame()
         self.frame.Create("Web Browser")
         if 'pywin.debugger' not in sys.modules:
             self.SetMainFrame(self.frame)

if __name__=='__main__':
     ##win32ui.Enable3dControls()
     win32ui.EnableControlContainer()
     ##app = win32ui.GetApp()
     app = MyApp()
     app.InitInstance()
     ##f = BrowserFrame()
     ##f.Create("Web Browser")
     if 'pywin.debugger' not in sys.modules:
         ##app.SetMainFrame(f)
         print "Run() ..."
         ##app.Run()
         print "Run() terminated."
         ##f.DestroyWindow()
         ##print "f.DestroyWindow() 'ed."
         ##os._exit(0)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: webbcrash.py
Type: text/x-python
Size: 2860 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-win32/attachments/20111227/42b575e3/attachment.py>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: startframework.pyw
URL: <http://mail.python.org/pipermail/python-win32/attachments/20111227/42b575e3/attachment.ksh>


More information about the python-win32 mailing list