Finding source of seg fault

The login dialog for my application should be shown modal. However, when I
add a ShowModal() command the application seg faults and I've not seen why.

   The sequence is:

   Within class PwSplashScreen() is the line
   self.fc = wx.FutureCall(4000, self.ShowLogin)

   The method contains:
   def ShowLogin(self):
             dlg = LoginDialog()
             dlg.ShowModal()
             dlg.Destroy()

   Originally ShowLogin() had only dlg.Show(), not .ShowModal(). I'm sure
this is a simple syntax error but I'm not seeing it and to more experienced
eyes it is probably obvious.

   Please show me what I've done incorrectly.

Rich

It may be a simple error, but I can’t tell. I use faulthandler to gain some info on segfaults. I’ve had a few that ended up being Python and/or wxPython compiled-code errors, and the segfault traces helped me track down existing bug reports and their workarounds.

···

On Thursday, July 24, 2014 10:35:00 AM UTC-7, fuzzydoc wrote:

The login dialog for my application should be shown modal. However, when I

add a ShowModal() command the application seg faults and I’ve not seen why.

The sequence is:

Within class PwSplashScreen() is the line

     self.fc = wx.FutureCall(4000, self.ShowLogin)

The method contains:

     def ShowLogin(self):

         dlg = LoginDialog()

         dlg.ShowModal()

         dlg.Destroy()

Originally ShowLogin() had only dlg.Show(), not .ShowModal(). I’m sure

this is a simple syntax error but I’m not seeing it and to more experienced

eyes it is probably obvious.

Please show me what I’ve done incorrectly.

Rich

Would you mind posting the full seg fault / trace back?

···

On Thursday, July 24, 2014 1:35:00 PM UTC-4, fuzzydoc wrote:

The login dialog for my application should be shown modal. However, when I

add a ShowModal() command the application seg faults and I’ve not seen why.

The sequence is:

Within class PwSplashScreen() is the line

     self.fc = wx.FutureCall(4000, self.ShowLogin)

The method contains:

     def ShowLogin(self):

         dlg = LoginDialog()

         dlg.ShowModal()

         dlg.Destroy()

Originally ShowLogin() had only dlg.Show(), not .ShowModal(). I’m sure

this is a simple syntax error but I’m not seeing it and to more experienced

eyes it is probably obvious.

Please show me what I’ve done incorrectly.

Rich

That appears to be a Microsoft-specific tool. I run linux.

   The problem is associated with the call to ShowModal() rather than just
Show(). The latter allows the login dialog to properly close without a
segfault and core dump. Ergo, I must need to show the dialog other than in
that class ... I suspect.

Thanks,

Rich

···

On Thu, 24 Jul 2014, Nathan McCorkle wrote:

It may be a simple error, but I can't tell. I use faulthandler

Mike,

   I would not mind if that was presented to me. What happens is that the
application shuts down with the message that a segmentation fault occurred;
e.g.,

[rshepard@salmo ~/development/project/trunk/src]$ ./pw.py Segmentation fault

   I suspect it's caused by ShowModal() being called in the SplashScreen
class rather than in the Login dialog.

Rich

···

On Thu, 24 Jul 2014, Mike Stover wrote:

Would you mind posting the full seg fault / trace back?

As I wrote earlier, there is nothing to see other than the string
'segmentation fault'.

   What I can provide are the two classes.

class PwSplashScreen(wx.SplashScreen):
     def __init__(self):
         bmp =
wx.Image(opj(os.path.abspath(os.path.join(os.path.split(__file__)[0],"bitmaps","splash.png")))).ConvertToBitmap()
         wx.SplashScreen.__init__(self, bmp,
                                  wx.SPLASH_CENTER_ON_SCREEN|wx.SPLASH_TIMEOUT, 3000, None, -1)
         self.Bind(wx.EVT_CLOSE, self.OnClose)
         self.fc = wx.FutureCall(4000, self.ShowLogin)

     def OnClose(self, evt):
         # Make sure the default handler runs too so this window gets
         # destroyed
         evt.Skip()
         self.Hide()

         # if the timer is still running then go ahead and show the main
         # frame now
         if self.fc.IsRunning():
             self.fc.Stop()
             self.ShowLogin()

     def ShowLogin(self):
         dlg = LoginDialog()
         dlg.ShowModal()
         dlg.Destroy()

     def ShowMain(self):
         if self.fc.IsRunning():
             self.Raise()

class LoginDialog(wx.Dialog):
     def __init__(self, *args, **kwds):

         super(LoginDialog, self).__init__(None)

         topSizer = wx.BoxSizer(wx.VERTICAL)

         header = wx.StaticText(self, -1, "PermitWatch Login")
         topSizer.Add(header, 0, wx.ALIGN_CENTER|wx.ALL, 5)

         unameBox = wx.BoxSizer(wx.HORIZONTAL)

         lab = wx.StaticText(self, -1, "Username: ")
         unameBox.Add(lab, 0, wx.ALIGN_CENTER|wx.ALL, 5)

         self.unameTxt = wx.TextCtrl(self, -1, "", size=(150,-1),style=wx.TAB_TRAVERSAL|
                              wx.TE_PROCESS_ENTER|wx.RAISED_BORDER )
         self.unameTxt.SetHelpText("Username is case sensitive.")
         unameBox.Add(self.unameTxt, 1, wx.ALIGN_CENTER|wx.ALL, 5)

         topSizer.Add(unameBox, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

         pwBox = wx.BoxSizer(wx.HORIZONTAL)

         lab = wx.StaticText(self, -1, "Password: ")
         pwBox.Add(lab, 0, wx.ALIGN_CENTER|wx.ALL, 5)

         self.pwTxt = wx.TextCtrl(self, -1, "", size=(150,-1), style=wx.TE_PASSWORD|
                               wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.RAISED_BORDER)
         self.pwTxt.SetHelpText("Password is case sensitive and must be longer than 6 characters.")
         pwBox.Add(self.pwTxt, 0, wx.ALIGN_CENTER|wx.ALL, 5)

         topSizer.Add(pwBox, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

         btnSizer = wx.StdDialogButtonSizer()

         OkBtn = wx.Button(self, wx.ID_OK)
         OkBtn.SetHelpText("The OK button allows logging in.")
         OkBtn.SetDefault()
         btnSizer.AddButton(OkBtn)
         self.Bind(wx.EVT_BUTTON, self.OnOK, OkBtn)

         CancelBtn = wx.Button(self, wx.ID_CANCEL)
         CancelBtn.SetHelpText("The Cancel button quits the application.")
         btnSizer.AddButton(CancelBtn)
         btnSizer.Realize()
         self.Bind(wx.EVT_BUTTON, self.OnClose, CancelBtn)

         topSizer.Add(btnSizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

         self.SetSizer(topSizer)
         topSizer.Fit(self)

     def OnOK(self, event):
         wx.MessageBox("You entered username %s and %s password." % (self.unameTxt.GetValue(), self.pwTxt.GetValue()))
         # Add validity checking here.
         self.Destroy()

     def OnClose(self, event):
         self.Destroy()

···

On Thu, 24 Jul 2014, Mike Stover wrote:

Would you mind posting the full seg fault / trace back?

$> lsb_release -a
  Distributor ID: Debian
  Description: Debian GNU/Linux testing (jessie)
  Release: testing
  Codename: jessie

  $> apt-cache policy python-faulthandler
  python-faulthandler:
    Installiert: 2.0-1
    Installationskandidat: 2.0-1
    Versionstabelle:
   *** 2.0-1 0
          500 Index of /debian wheezy/main i386 Packages
          990 Index of /debian jessie/main i386 Packages
          990 ftp://ftp.de.debian.org/debian/ testing/main i386 Packages
           50 ftp://ftp.de.debian.org/debian/ unstable/main i386 Packages
          100 /var/lib/dpkg/status

Karsten

···

On Thu, Jul 24, 2014 at 11:26:24AM -0700, Rich Shepard wrote:

>It may be a simple error, but I can't tell. I use faulthandler

  That appears to be a Microsoft-specific tool. I run linux.

--
GPG key ID E4071346 @ gpg-keyserver.de
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

Karsten,

   Interesting that my first search term for 'python fault handler' did not
find the same results as 'python-faulthandler'. If there's not a Slackware
package I'll just build from source if need be.

Thanks,

Rich

···

On Thu, 24 Jul 2014, Karsten Hilbert wrote:

  $> lsb_release -a
  Distributor ID: Debian
  Description: Debian GNU/Linux testing (jessie)
  Release: testing
  Codename: jessie

Karsten,

   It's included in Python3, but not Python2. I grabbed the source tarball
and will build and install in for Python-2.7.5.

Thanks,

Rich

···

On Thu, 24 Jul 2014, Karsten Hilbert wrote:

  Distributor ID: Debian
  Description: Debian GNU/Linux testing (jessie)
  Release: testing
  Codename: jessie

Fatal Python error: Segmentation fault

Current thread 0xb73c56c0:
   File "/usr/lib/python2.7/site-packages/wx-3.0-gtk2/wx/_core.py", line 7952
in MainLoop
   File "/usr/lib/python2.7/site-packages/wx-3.0-gtk2/wx/_core.py", line 8660
in MainLoop
   File "./pw.py", line 3427 in main
   File "./pw.py", line 3431 in <module>
Segmentation fault

   The MainLoop lines in the code are:

def main():
     app = PwApp(False)
     app.MainLoop() # line 3427

if __name__ == '__main__':
     __name__ = 'Main'
     main() # line 3431

   In _core.py:

     def MainLoop(self):
         """Execute the main GUI event loop"""
         wx.PyApp.MainLoop(self) # line 8660
         self.RestoreStdio()

     def MainLoop(*args, **kwargs):
         """
         MainLoop(self) -> int

         Execute the main GUI loop, the function doesn't normally return un
         all top level windows have been closed and destroyed.
         """
         return _core_.PyApp_MainLoop(*args, **kwargs) # line 7952

   Does this help?

Thanks,

Rich

···

On Thu, 24 Jul 2014, Mike Stover wrote:

Would you mind posting the full seg fault / trace back?

Rich,

you may want to take a look at how GNUmed does things. We
don't have a splash screen (well, of sorts) but we certainly
do show a login dialog before setting up the main frame.

  http://gitorious.org/gnumed

Karsten

···

--
GPG key ID E4071346 @ gpg-keyserver.de
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

Karsten,

   I certainly will. The problem solved by the current flow (which works as
long as the login dialog is not modal) was the login dialog appearing
immediately on top of the splash screen.

   Thanks very much to the pointer to python's faulthandler. It was an easy
installation on 2.7.5 ('python setup.py install') and it works as
advertised. If only the output made sense to me I'd know how to fix the
problem.

Rich

···

On Thu, 24 Jul 2014, Karsten Hilbert wrote:

you may want to take a look at how GNUmed does things. We don't have a
splash screen (well, of sorts) but we certainly do show a login dialog
before setting up the main frame.
  http://gitorious.org/gnumed

Hmm unfortunately those are the same lines that a bad wxPython binary was breaking on me. I was also using 3.0 Classic but it was on Windows (so 3.0.0-Classic-msw). The latest segfault was unfortunately the result of some Windows-specific (I believe) bug relating to how dynamic loaded libraries were being loaded. I know linux can dynamically load/unload kernel modules, but I’ve been developing for Windows most of this year so my linux-foo is a bit dusty.

···

On Thursday, July 24, 2014 12:20:24 PM UTC-7, fuzzydoc wrote:

On Thu, 24 Jul 2014, Mike Stover wrote:

Would you mind posting the full seg fault / trace back?

Fatal Python error: Segmentation fault

Current thread 0xb73c56c0:

File “/usr/lib/python2.7/site-packages/wx-3.0-gtk2/wx/_core.py”, line 7952

in MainLoop

File “/usr/lib/python2.7/site-packages/wx-3.0-gtk2/wx/_core.py”, line 8660

in MainLoop

File “./pw.py”, line 3427 in main

File “./pw.py”, line 3431 in

Segmentation fault

Have you already started a wx.App()? Maybe ShowModal wants an App to exist?

···

On Thursday, July 24, 2014 11:44:51 AM UTC-7, fuzzydoc wrote:

On Thu, 24 Jul 2014, Mike Stover wrote:

Would you mind posting the full seg fault / trace back?

As I wrote earlier, there is nothing to see other than the string

‘segmentation fault’.

What I can provide are the two classes.

class PwSplashScreen(wx.SplashScreen):

 def __init__(self):

     bmp =

wx.Image(opj(os.path.abspath(os.path.join(os.path.split(file)[0],“bitmaps”,“splash.png”)))).ConvertToBitmap()

     wx.SplashScreen.__init__(self, bmp,

                              wx.SPLASH_CENTER_ON_SCREEN|wx.SPLASH_TIMEOUT, 3000, None, -1)

     self.Bind(wx.EVT_CLOSE, self.OnClose)

     self.fc = wx.FutureCall(4000, self.ShowLogin)



 def OnClose(self, evt):

     # Make sure the default handler runs too so this window gets

     # destroyed

     evt.Skip()

     self.Hide()



     # if the timer is still running then go ahead and show the main

     # frame now

     if self.fc.IsRunning():

         self.fc.Stop()

         self.ShowLogin()



 def ShowLogin(self):

     dlg = LoginDialog()

     dlg.ShowModal()

     dlg.Destroy()



 def ShowMain(self):

     if self.fc.IsRunning():

         self.Raise()

class LoginDialog(wx.Dialog):

 def __init__(self, *args, **kwds):



     super(LoginDialog, self).__init__(None)



     topSizer = wx.BoxSizer(wx.VERTICAL)



     header = wx.StaticText(self, -1, "PermitWatch Login")

     topSizer.Add(header, 0, wx.ALIGN_CENTER|wx.ALL, 5)



     unameBox = wx.BoxSizer(wx.HORIZONTAL)



     lab = wx.StaticText(self, -1, "Username: ")

     unameBox.Add(lab, 0, wx.ALIGN_CENTER|wx.ALL, 5)



     self.unameTxt = wx.TextCtrl(self, -1, "", size=(150,-1),style=wx.TAB_TRAVERSAL|

                          wx.TE_PROCESS_ENTER|wx.RAISED_BORDER )

     self.unameTxt.SetHelpText("Username is case sensitive.")

     unameBox.Add(self.unameTxt, 1, wx.ALIGN_CENTER|wx.ALL, 5)



     topSizer.Add(unameBox, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)



     pwBox = wx.BoxSizer(wx.HORIZONTAL)



     lab = wx.StaticText(self, -1, "Password: ")

     pwBox.Add(lab, 0, wx.ALIGN_CENTER|wx.ALL, 5)



     self.pwTxt = wx.TextCtrl(self, -1, "", size=(150,-1), style=wx.TE_PASSWORD|

                           wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.RAISED_BORDER)

     self.pwTxt.SetHelpText("Password is case sensitive and must be longer than 6 characters.")

     pwBox.Add(self.pwTxt, 0, wx.ALIGN_CENTER|wx.ALL, 5)



     topSizer.Add(pwBox, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)



     btnSizer = wx.StdDialogButtonSizer()



     OkBtn = wx.Button(self, wx.ID_OK)

     OkBtn.SetHelpText("The OK button allows logging in.")

     OkBtn.SetDefault()

     btnSizer.AddButton(OkBtn)

     self.Bind(wx.EVT_BUTTON, self.OnOK, OkBtn)



     CancelBtn = wx.Button(self, wx.ID_CANCEL)

     CancelBtn.SetHelpText("The Cancel button quits the application.")

     btnSizer.AddButton(CancelBtn)

     btnSizer.Realize()

     self.Bind(wx.EVT_BUTTON, self.OnClose, CancelBtn)



     topSizer.Add(btnSizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)



     self.SetSizer(topSizer)

     topSizer.Fit(self)



 def OnOK(self, event):

     wx.MessageBox("You entered username %s and %s password." % (self.unameTxt.GetValue(), self.pwTxt.GetValue()))

     # Add validity checking here.

     self.Destroy()





 def OnClose(self, event):

     self.Destroy()

Nathan,

   That's both interesting and encouraging: it was not something specific I
did incorrectly.

   This suggests to me that I need a new flow direction; perhaps calling
Login() from MainFrame() rather than from SplashScreen().

   What I want the user to see is 1) Splash screen, 2) modal Login dialog box
(only successfully logged in users can access any of the application's
functions, 3) the main application notebook.

   The current flow has MainFrame call SplashScreen that calls LoginDialog.
When the dialog closes, SplashScreen calls the main loop.

Rich

···

On Thu, 24 Jul 2014, Nathan McCorkle wrote:

Hmm unfortunately those are the same lines that a bad wxPython binary was
breaking on me.

Nathan,

   I think so. I'll run the app through winpdb and see where it goes.

Rich

···

On Thu, 24 Jul 2014, Nathan McCorkle wrote:

Have you already started a wx.App()? Maybe ShowModal wants an App to exist?

Hi Rich,

I am on Windows, so result might be different.

When do you see the crash?

Using your code, I see the following traceback when I click OK or Cancel on the login dialog.

File "d:\devOther\aaSamples\RichShepard\loginissue.py", line 121, in <module>
   app.MainLoop()
File "c:\Python27\Lib\site-packages\wx-2.9.5-msw\wx\_core.py", line 8660, in MainLoop
   wx.PyApp.MainLoop(self)
File "c:\Python27\Lib\site-packages\wx-2.9.5-msw\wx\_core.py", line 7952, in MainLoop
   return _core_.PyApp_MainLoop(*args, **kwargs)
File "d:\devOther\aaSamples\RichShepard\loginissue.py", line 26, in OnClose
   self.ShowLogin()
File "d:\devOther\aaSamples\RichShepard\loginissue.py", line 31, in ShowLogin
   dlg.Destroy()
File "c:\Python27\Lib\site-packages\wx-2.9.5-msw\wx\_core.py", line 16712, in __getattr__
   raise PyDeadObjectError(self.attrStr % self._name)

wx._core.PyDeadObjectError: The C++ part of the LoginDialog object has been deleted, attribute access no longer allowed.

I then started to experiment with this, removed the 'Destroy' calls and then I started to see hard crashes if I did 'self.caller.showLogin' from the OnClose of the splash (and commented the 'self.showLogin' in the OnInit), when I traced it with the WingIDE debugger I saw that the 'self.caller.showLogin()' line was called again when the 'self.mainFrame.Show()' line was reached. I don't understand why this is happening as the splash was gone by that time.

I didn't like the line up of the controls, so couldn't resist redoing it with sized_controls:-) .

loginissue.py (3.85 KB)

When do you see the crash?

Werner,

   Only when Show(Login) is changed to ShowModal(Login).

Using your code, I see the following traceback when I click OK or Cancel on the login dialog.

   With faulthandler.enable set, I posted the 4 lines it returned: two in my
code and two in _core.py.

I then started to experiment with this, removed the 'Destroy' calls and
then I started to see hard crashes if I did 'self.caller.showLogin' from
the OnClose of the splash (and commented the 'self.showLogin' in the
OnInit), when I traced it with the WingIDE debugger I saw that the
'self.caller.showLogin()' line was called again when the
'self.mainFrame.Show()' line was reached. I don't understand why this is
happening as the splash was gone by that time.

   I expereimented, too. Changing .Destroy() to .Close() froze the
application; I had to manually kill the python process. Removing .Destroy()
also meant manually killing the process. That there are dialog close
statements in both LoginDialog() and pwSplashScreen() may be part of the
problem. That it occurs only when the dialog is in modal mode requires
greater understanding than I have of what is going on under the hood.

   What I'm going to work on (after writing the last 4 data entry pages) is
having the main loop first call the splash screen. When that times out or is
manually closed, then main loop calls the model login dialog. I tried that
first and failed (the login dialog kept displaying over the splash screen)
which is why I accepted suggestions to call login from the splash screen
class. My suspecion is that the application is digging itself into a hole
rather than calling each class sequentially and separately.

I didn't like the line up of the controls, so couldn't resist redoing it with sized_controls:-) .

   My attention is to first get the application working as it needs to, then
tweak appearance and add bells and whistles.

Thanks,

Rich

···

On Fri, 25 Jul 2014, Werner wrote:

Hi Rich,

When do you see the crash?

Werner,

  Only when Show(Login) is changed to ShowModal(Login).

But when does it crash, when the line ShowModal is executed or when closing, or .....?

With the attached code I can call the Login dialog from the splash and don't see any crashes any more. The main change was to use wx.CallAfter instead of directly calling the method to show the login dialog.
...

I didn't like the line up of the controls, so couldn't resist redoing it with sized_controls:-) .

  My attention is to first get the application working as it needs to, then
tweak appearance and add bells and whistles.

Would do the same, just wanted to show you that with sized_controls you get very easily nicely laid out displays using sizers without having to deal much with sizers.

Hope this helps
Werner

loginissue.py (3.78 KB)

···

On 7/25/2014 14:51, Rich Shepard wrote:

On Fri, 25 Jul 2014, Werner wrote:

But when does it crash, when the line ShowModal is executed or when closing, or .....?

Werner,

   When closed.

With the attached code I can call the Login dialog from the splash and don't see any crashes any more. The main change was to use wx.CallAfter instead of directly calling the method to show the login dialog.

   Ah, ha! Using wx.CallAfter makes so much sense in this situation. Thanks
for making me aware of it.

Would do the same, just wanted to show you that with sized_controls you get very easily nicely laid out displays using sizers without having to deal much with sizers.

   Good to know.

Hope this helps

   Yep, it does.

Thanks,

Rich

···

On Fri, 25 Jul 2014, Werner wrote: