Mind your Ps, Qs and CCallbacks

Been debugging a weird error in GLUT this evening.  Basically if you went into OpenGLContext and used a right-mouse-click-and-drag to rotate around the center-of-view, there would, every once in a while, be a seg-fault.  It didn't happen if you rotated a bit more slowly, or you turned on full logging to see what's going on, basically it happened only if you were moving the mouse at the time you released the button...

OpenGLContext registers a handler on the right-mouse operation which creates an examination-mode event handler which lives solely for the duration of the drag, and which "captures" further mouse motions via (in the case of a GLUT context) GLUT callbacks.  The right-mouse-up event de-registers the mouse-motion event handler.

Oops.  Apparently it's possible for GLUT to produce mouse-move events for an event handler even after the mouse-motion event handler is de-registered.  Seems the events are already in the GLUT queue, so they wind up running after the handler has been destroyed.  Don't know why this only showed up now, but it's likely something I need to guard against at the PyOpenGL level.  (Haven't figured out a clean way to do that yet, though, I'm thinking maybe of starting a GLUT timer which fires in X seconds and does the actual release of the Python-side function).

Other than this, the cleaned-up code generation using the Pyglet generator seems to be working for all of GL, GLU and GLUT.  I should likely add GLE to the set and then see about committing the changes.  In other PyOpenGL news, seems likely that we'll get access to the OpenGL 2.1 (or even 3.0) man-page docbook file for the documentation.


  1. Carl Witty

    Carl Witty on 09/04/2008 12:52 p.m. #

    I don't know exactly how PyOpenGL or GLUT works, so apologies if my proposal is irrelevant or unworkable.

    I imagine that GLUT has a callback interface where you give it a C function pointer and a void*, and you're passing a Python function as the void* (and decref'ing the function when you deregister the callback).

    I suggest that instead you pass a single-element Python list containing the Python function as the void*; when you deregister the callback, replace the Python function by None in the list. Never decref the list; when you reregister the callback, replace the None by the Python function and reuse the same list. (So this creates a permanent memory leak of up to one Python list per type of callback; annoying, but much better than crashing.)

  2. Mike Fletcher

    Mike Fletcher on 09/05/2008 8:38 a.m. #

    Actually, the callback always has to be a callable object. The problem is actually that we really *do* want to allow de-registering some events (e.g. mouse-move), as processing them even with a null operation will take a noticeable amount of processing time. To make it safe we'd likely need to do something crazy like an Idle-timer-based destroy of the c-level callback object.

Comments are closed.


Pingbacks are closed.