[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] event getting corrupted



I'm a little confused - you said you get a "segmentation error", and you mentioned running a debugger, but you are showing a python error. So do you get a real segmentation fault? Like bad memory access that drops out of python and all that? If so, you haven't captured that error in the right kind of debugger for seg faults (gdb) yet.

Assuming you are getting a seg fault, then that sucks.  If it were me in that case, I'd probably see if I can set up some system to force the error to happen. Like say make the game run through the conditions that you see the error in now, and make it run over night - or maybe set up some kind of automation to record and playback some play, and again, run it all night.

The reason getting a stable reproducing case is so important, is then you can binary search this. Like disable all blitting, or turn off the music, etc.

As far as the python stack trace goes, if you are getting a seg fault, then the weirdness of the python stack makes it seem likely that memory corruption happened between the event.pos and event.button lines, as you pointed out. Is this python stack reproducible? Have you seen it multiple times? If so, then it seems like it could be code that executes synchronously between those 2 lines, in which case tossing a ton of asserts or "temp = event.button" lines in the mouse_button_up would help you narrow down the lines that trigger things next time this in-python exception triggers? If on the other hand you haven't seen it before/can't reporoduce it, it may just be a red herring, and the corruption could be happening asynchronously in some other thread - maybe it could be the music?

So what OS and versions of stuff you using when you get the error? Have you been able to try the code on other platforms? Any other libraries besides pygame used with this program? Any idea when exactly it started occurring in relation to your code? Any code of yours that seems like something that could be causing the problem (like your own c compiled extensions)? I don't suppose you are blitting a surface to itself anywhere and using Linux?


On Wed, Sep 16, 2009 at 11:36 AM, Bo Jangeborg <bo@xxxxxxxxxxx> wrote:
I have seen a troubling error for some time now.
Occasionally I get a segmentation error with no indication of what
went wrong. The error is not repeatable in a reliable way and I get
no error trace. Repeating the error can take hours.

After seeing this I have tried to pin down, with the debugger running,
what's going wrong but the nearest I can get is that the event object
gets turned into a long at different times.

Running with a debugger I got this trace. I have included the calling
line were you can see that the event seem to be correct, but at some
point the event object seem to become corrupted.
Included is also the code between the call and the eventual point
of error. I am at loss at what may be going wrong.

Bo)

Traceback (most recent call last):
 File "C:\Program Files\eclipse\plugins\org.python.pydev.debug_1.4.7.2843\pysrc\pydevd.py", line 881, in <module>
  debugger.run(setup['file'], None, None)
 File "C:\Program Files\eclipse\plugins\org.python.pydev.debug_1.4.7.2843\pysrc\pydevd.py", line 710, in run
  execfile(file, globals, locals) #execute the script
 File "C:\Projekt\eclipse\Pyos\Program\Solitaire\solitaire.py", line 761, in <module>
  main()
 File "C:\Projekt\eclipse\Pyos\Program\Solitaire\solitaire.py", line 80, in main
  if screen.main_loop(app):
 File "C:\Projekt\eclipse\Pyos\System\widgets\gui.py", line 328, in main_loop
  = self.mouse_button_up(event, mob_pos, mousemove)
 File "C:\Projekt\eclipse\Pyos\System\widgets\gui.py", line 573, in mouse_button_up
  if event.button == 1:
AttributeError: 'long' object has no attribute 'button'


elif event.type is MOUSEBUTTONUP:
   mob_pos, mousemove, mouse_pos, hit_pos \
               = self.mouse_button_up(event, mob_pos, mousemove)



  def mouse_button_up(self, event, mob_pos, mousemove):
      ''' handle mouse button up events'''
      mousebtn_event = False
      mouse_pos = event.pos
      widget, hit_pos = self.mouse_hit_widget(mouse_pos[0],
                                          mouse_pos[1])
      if widget is None or not widget.enabled:
          self.moving_object = None
          self.repeating_object = None
          self.last_over_drop_widget = None
      else:
          event_data = {'hit_pos':hit_pos, 'over_widget':widget}
          event_data['gui'] = self
          if widget and widget.exists('event_click_release_data'):
              event_data.update(widget.event_click_release_data)
          #InsideButton  (Left)
          if event.button == 1:



  def mouse_hit_widget(self, hit_pos_x, hit_pos_y, draged_widget=None,
                      dropreciever=False, mouse_down=False, mouse_over=False):
      ''' Return the first valid widget under the mouse pointer'''
      widget_hit, hit_pos = _mouse_hit_widget(self, hit_pos_x, hit_pos_y,
                                               draged_widget, dropreciever)
      if not widget_hit is None:
          modal_lock = widget_hit.app.get_modal()
          if modal_lock:
              if modal_lock.close_on_focuschange\
              and not (modal_lock in widget_hit.get_actionpath())\
              and mouse_down:
                  #Close the modal widget if something else
                  # is being clicked. Popups, such as menues f.ex,
                  #  would have this behaviour.
                  event_data = {'mouse_over':widget_hit,
                                'close_on_focuschange':True}
                  modal_lock.event_close(event_data)
              elif not (widget_hit is modal_lock) \
              and not (mouse_over and modal_lock.close_on_focuschange):
                  if not (modal_lock in widget_hit.get_actionpath()):
                      widget_hit = None
      return widget_hit, hit_pos


def _mouse_hit_widget(wid, hit_pos_x, hit_pos_y, draged_widget=None,
                    dropreciever=False):
  ''' Loop until a valid widget is under the mouse pointer'''
  hit_pos_x -= wid.rect.left
  hit_pos_y -= wid.rect.top
  widget_hit = None
  hit_pos = False
  for widget in wid.widgets[::-1]:
      if widget.rect.top <= hit_pos_y \
      and widget.rect.bottom > hit_pos_y \
      and widget.rect.left <= hit_pos_x \
      and widget.rect.right > hit_pos_x\
      and widget.visible \
      and widget.visible_to_hit \
      and widget != draged_widget:
          if widget.widgets:
              widget_hit, hit_pos = _mouse_hit_widget(widget, hit_pos_x,
                                                  hit_pos_y, draged_widget,
                                                  dropreciever)
              if widget_hit:
                  break
          if dropreciever:
              if not hasattr(widget, 'dropreciever')\
              or widget.dropreciever != True:
                  continue
          if widget.image and not type(widget.image) == type(True):
              _image_offset = (hit_pos_x - widget.rect.left,
                                hit_pos_y - widget.rect.top)
              if widget.flags & PIXELALPHA:
                  if widget.image.get_at(_image_offset)[3] != 0:
                      if not widget.image.get_colorkey() is None:
                          if widget.image.get_at(_image_offset) !=\
                          widget.image.get_colorkey():
                              widget_hit = widget
                      else:
                          widget_hit = widget
                      if widget_hit and hasattr(widget, 'on_hit_image'):
                          widget_hit = widget.on_hit_image(_image_offset)
              elif not widget.image.get_colorkey() is None:
                  if widget.image.get_at(_image_offset) !=\
                  widget.image.get_colorkey():
                      widget_hit = widget
              else:
                  widget_hit = widget
          else:
              if hasattr(widget, 'paper'):
                  widget_hit = widget
          if widget_hit:
              hit_pos = (hit_pos_x - widget_hit.rect.left,
                          hit_pos_y - widget_hit.rect.top)
              break
  if not widget_hit and isinstance(wid, Gui):
      widget_hit = wid
      hit_pos = (hit_pos_x, hit_pos_y)
  return widget_hit, hit_pos