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)
# 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)
#######################################################################################
##
## Fires up the PythonWin framework via normal python(w).exe (py1.5.2 tested)
##
#######################################################################################
import sys, win32ui, win32api, win32con
# store original console stdout/in
constdout=sys.constdout=sys.stdout
constdin=sys.constdin=sys.stdin
def do(*paths):
import pywin.framework.startup
from pywin.framework.intpyapp import thisApp
thisApp.MakeExistingDDEConnection = lambda:None # we can have more
Pythonwin's this way
app = thisApp
app.InitInstance()
try: win32api.SetConsoleTitle('PyWin Console')
except win32api.error: pass
#for path in args:
# app.OpenDocumentFile(path)
app.Run()
def do2():
import pywin.framework.startup
from pywin.framework.intpyapp import thisApp
thisApp.MakeExistingDDEConnection = lambda:None
app = thisApp
win32ui.LoadStdProfileSettings=lambda x:None
app.InitInstance()
app.frame.ShowWindow(win32con.SW_SHOW)
try: win32api.SetConsoleTitle('PyWin Console')
except win32api.error: pass
def do3():
import thread
thread.start_new_thread( do2, () )
if __name__=='__main__' :
try:
del sys.argv[0] # prevent this script from being loaded into the editor
except IndexError:
pass
do()
_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32