Re: OpenGL/GLUT examples crashing: known problem?

[cc-ed to hopengl list, probably more suited for follow-ups?]
Hi Tim,
not sure whether this helps, but I just compiled and ran the redbook
examples here (win98se, ghc6.4), and all but 2 looked well-behaved.
As for parameters, "fgrep -w args *hs" shows that the only programs
that admit to inspecting their parameters have a sensible default. More
interesting are the interactions, as far as they go beyond <esc> for
exit - check the keyboard functions in the sources to get an idea.
Btw, you probably shouldn't redirect the (error-)output to /dev/null
if you want to know what goes wrong;-) On my ancient configuration,
several examples report unknown OpenGL calls or missing extensions.
In fact all but one of those programs which "fail" on my system (9, not
the same as in your list, but for MVArray and Quadric) give me such
explanations (the one exception was Quadric, with which I couldn't
see anything wrong on the screen, and which does in fact give me
an "ok" when run again on its own..).
[Sven:]
Two of the examples crashed on me:-( Tess.hs & TessWind.hs. As
if that wasn't bad enough, I had to remove them from the test loop
because they don't leave my opengl system in a good state: no
obvious havoc outside the examples, but if I ran the test loop a
second time, many examples only showed a black screen, or
missing features.
Never mind whether or not they should work, but what about the
crash? Is that just a case of bad programming, or something that
the library should catch, or a safety hole, or something wrong
with my setup?
-- ??
Prelude Graphics.Rendering.OpenGL.GL> get glVersion >>= print
""
Prelude Graphics.Rendering.OpenGL> get gluVersion >>= print
"1.2.2.0 Microsoft Corporation"
Prelude Graphics.UI.GLUT> get glutVersion >>= print
"GLUT 3.7"
Btw, is there a way to reset the opengl system to a sane state in
software? Or are there some invalid assumptions about default
state in the other examples?
Cheers,
Claus
----- Original Message -----
From: "Tim Smith"
Hi! I just got GLUT to compile with a recent GHC (tried both ghc6.4 and a fresh CVS), see:
https://sourceforge.net/tracker/?func=detail&atid=108032&aid=1177838&group_id=8032
Anyways, now I did 'gmake' in GLUT/examples. Everything builds fine, but a number of the examples don't work. I.e., in RedBook:
2:39 ~/local/src/build/libraries/GLUT/examples/RedBook$ for f in `find . -type f -perm 755 -print`; do if $f >/dev/null 2>&1; then echo "$f OK"; else echo "$f failed"; fi; done ./Alpha OK ./BezCurve OK ./BezMesh failed ./BezSurf OK ./BlendEqn OK ./Checker OK ./Clip failed ./ColorMat failed ./ColorMatrix OK ./ColorTable OK ./Combiner OK ./Convolution OK ./Cube OK ./CubeMap failed ./DList OK ./Double OK ./DrawF OK ./Feedback OK ./Fog failed ./FogCoord OK ./Font OK ./Hello OK ./Histogram OK ./Image OK ./Light failed ./Lines OK ./MVArray failed ./Material failed ./Minmax OK ./Mipmap OK ./Model OK ./MoveLight failed ./MultiTex OK ./PickDepth OK ./PickSquare OK ./Planet failed ./Polys OK ./Quadric failed ./Robot OK ./Scene failed ./Select OK ./ShadowMap failed ./Smooth OK ./SurfPoints OK ./Surface failed ./Teapots failed ./Tess OK ./TexBind OK ./TessWind OK ./TexGen failed ./TexProx OK ./TexSub OK ./Texture3D OK ./TextureSurf OK ./Trim failed ./UnProject OK ./VArray OK ./Wrap OK
This is probably some known bug, but I wanted to check. If so, does anyone know what the parameters are on what can be used, and what will core dump? If it's not a known bug, I'll file a bug report - any other info that would be helpful?
Thank you!
Tim -- If you're not part of the solution, you're part of the precipitate. _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Claus, Sven & all,
On 2005 Apr 09, Claus Reinke
not sure whether this helps, but I just compiled and ran the redbook examples here (win98se, ghc6.4), and all but 2 looked well-behaved.
Thanks for the reply, Claus! It's good to know that the examples are working for you - I know it's something that *could* work for me.
As for parameters, "fgrep -w args *hs" shows that the only programs that admit to inspecting their parameters have a sensible default. More interesting are the interactions, as far as they go beyond <esc> for exit - check the keyboard functions in the sources to get an idea.
Btw, you probably shouldn't redirect the (error-)output to /dev/null if you want to know what goes wrong;-) On my ancient configuration, several examples report unknown OpenGL calls or missing extensions.
I should have mentioned; they're all dumping core, terminated with SIGBUS (except for MVArray, which requires a missing extension for me). I ran all the failing ones under gdb, just to see if I could get any info. They failed in several different functions. Some failed in gluSphere(), like: #0 0x281612b7 in gluSphere () from /usr/X11R6/lib/libGLU.so.1 #1 0x280ce2a2 in glutWireSphere () from /usr/X11R6/lib/libglut.so.3 #2 0x0804d47d in s4HC_info () #3 0x00000000 in ?? () #4 0x3ff00000 in ?? () #5 0x00000014 in ?? () ... A number failed in r200UpdateMaterial, like: #0 0x28726bad in r200UpdateMaterial () from /usr/X11R6/lib/modules/dri/r200_dri.so #1 0x28728c93 in r200ValidateState () from /usr/X11R6/lib/modules/dri/r200_dri.so #2 0x28746289 in r200VtxfmtInvalidate () from /usr/X11R6/lib/modules/dri/r200_dri.so #3 0x287e648c in _tnl_wrap_filled_vertex () from /usr/X11R6/lib/modules/dri/r200_dri.so #4 0x287c452e in _mesa_init_varray () from /usr/X11R6/lib/modules/dri/r200_dri.so #5 0x281a4a86 in OpenGLSurfaceEvaluator::bgntfan () from /usr/X11R6/lib/libGLU.so.1 #6 0x281a4d0e in OpenGLSurfaceEvaluator::evalUStrip () from /usr/X11R6/lib/libGLU.so.1 ... There were a few other failure points (glutSolidCube, glutVideoPan). Taking the second one, from BezMesh.hs, I comment out the initlights call in the myInit function. Then the program runs to completion, and displays the mesh as a silhouette. Or, if I leave initlights in, but comment out the evalMesh2 call, then it works OK (but just displays a black window). I tried the C versions from here: http://www.opengl.org/resources/code/basics/redbook/ And compile them like this: cc -g -Wall -W -I/usr/X11R6/include -L/usr/X11R6/lib bezmesh.c \ -lglut -lGL -lGLU -lX11 -lm -o bezmesh Those C examples all work fine, except for aaindex and fogindex which can't find the visual needed - no core dumps. Unfortunately, I'm not sure where to start looking for the source of this problem. Even if no one else has seen something like this, maybe there is some good method of tracking down what part is broken? I'm using the OpenGL implementation that comes with X.org version 6.8.1 under FreeBSD 5-STABLE, and the libglut-6.0.1 port. Thanks, Tim -- If you're not part of the solution, you're part of the precipitate.

Hi! I haven't received any follow-ups to this message. I realize it's
a tough problem to sort out remotely.
Any ideas on where I might go next? I'd like to get to the bottom of
this crashing problem.
How can I narrow down where the problem lies? How can I determine why
an equivalent C program works, but the Haskell program crashes? Is
there a way to trace just exactly what the Haskell program is doing?
On 2005 Apr 10, Tim Smith
Claus, Sven & all,
On 2005 Apr 09, Claus Reinke
wrote: not sure whether this helps, but I just compiled and ran the redbook examples here (win98se, ghc6.4), and all but 2 looked well-behaved.
Thanks for the reply, Claus! It's good to know that the examples are working for you - I know it's something that *could* work for me.
As for parameters, "fgrep -w args *hs" shows that the only programs that admit to inspecting their parameters have a sensible default. More interesting are the interactions, as far as they go beyond <esc> for exit - check the keyboard functions in the sources to get an idea.
Btw, you probably shouldn't redirect the (error-)output to /dev/null if you want to know what goes wrong;-) On my ancient configuration, several examples report unknown OpenGL calls or missing extensions.
I should have mentioned; they're all dumping core, terminated with SIGBUS (except for MVArray, which requires a missing extension for me).
I ran all the failing ones under gdb, just to see if I could get any info. They failed in several different functions. Some failed in gluSphere(), like:
#0 0x281612b7 in gluSphere () from /usr/X11R6/lib/libGLU.so.1 #1 0x280ce2a2 in glutWireSphere () from /usr/X11R6/lib/libglut.so.3 #2 0x0804d47d in s4HC_info () #3 0x00000000 in ?? () #4 0x3ff00000 in ?? () #5 0x00000014 in ?? () ...
A number failed in r200UpdateMaterial, like:
#0 0x28726bad in r200UpdateMaterial () from /usr/X11R6/lib/modules/dri/r200_dri.so #1 0x28728c93 in r200ValidateState () from /usr/X11R6/lib/modules/dri/r200_dri.so #2 0x28746289 in r200VtxfmtInvalidate () from /usr/X11R6/lib/modules/dri/r200_dri.so #3 0x287e648c in _tnl_wrap_filled_vertex () from /usr/X11R6/lib/modules/dri/r200_dri.so #4 0x287c452e in _mesa_init_varray () from /usr/X11R6/lib/modules/dri/r200_dri.so #5 0x281a4a86 in OpenGLSurfaceEvaluator::bgntfan () from /usr/X11R6/lib/libGLU.so.1 #6 0x281a4d0e in OpenGLSurfaceEvaluator::evalUStrip () from /usr/X11R6/lib/libGLU.so.1 ...
There were a few other failure points (glutSolidCube, glutVideoPan).
Taking the second one, from BezMesh.hs, I comment out the initlights call in the myInit function. Then the program runs to completion, and displays the mesh as a silhouette.
Or, if I leave initlights in, but comment out the evalMesh2 call, then it works OK (but just displays a black window).
I tried the C versions from here:
http://www.opengl.org/resources/code/basics/redbook/
And compile them like this:
cc -g -Wall -W -I/usr/X11R6/include -L/usr/X11R6/lib bezmesh.c \ -lglut -lGL -lGLU -lX11 -lm -o bezmesh
Those C examples all work fine, except for aaindex and fogindex which can't find the visual needed - no core dumps.
Unfortunately, I'm not sure where to start looking for the source of this problem. Even if no one else has seen something like this, maybe there is some good method of tracking down what part is broken?
I'm using the OpenGL implementation that comes with X.org version 6.8.1 under FreeBSD 5-STABLE, and the libglut-6.0.1 port.
Thanks, Tim -- If you're not part of the solution, you're part of the precipitate.

I'm probably the wrong person to answer most of your questions, but
Any ideas on where I might go next? I'd like to get to the bottom of this crashing problem.
How can I narrow down where the problem lies? How can I determine why an equivalent C program works, but the Haskell program crashes? Is there a way to trace just exactly what the Haskell program is doing?
there are some opengl debuggers and tracers around - I'm googling for a free windows one, mac users seem to have such support provided by apple, other platforms have their own. I don't have any experience with these, but if they only show the opengl calls, it may be possible to compare the c and haskell runs, especially where the hopengl version tries to mimick the opengl version closely instead of introducing higher-level abstractions. I'd be interested in recommendations, if anyone has experience with such tools. cheers, claus

Claus Reinke wrote:
I'm probably the wrong person to answer most of your questions, but
Any ideas on where I might go next? I'd like to get to the bottom of this crashing problem.
How can I narrow down where the problem lies? How can I determine why an equivalent C program works, but the Haskell program crashes? Is there a way to trace just exactly what the Haskell program is doing?
there are some opengl debuggers and tracers around - I'm googling for a free windows one, mac users seem to have such support provided by apple, other platforms have their own. I don't have any experience with these, but if they only show the opengl calls, it may be possible to compare the c and haskell runs, especially where the hopengl version tries to mimick the opengl version closely instead of introducing higher-level abstractions.
I'd be interested in recommendations, if anyone has experience with such tools.
Even though I'm not experienced with it, GLinterceptor looks good and works on Windows. http://glintercept.nutty.org/ regards, Arjen

-------------------- 1. opengl tracers
Even though I'm not experienced with it, GLinterceptor looks good and works on Windows. http://glintercept.nutty.org/
thanks! they don't list win98, but this one does actually seem to work. before, I had tried two or three other products, with limited success (best was gltrace itself, but that fails to produce a log for me, even though it manages to count the calls... strange). didn't help me much in this case, though, as tess.c crashes before producing any log entries.. -------------------- 2. tess (and most likely all gl/glu code that uses callbacks on windows, at least on windows 98 with cygwin/mingw) made some progress anyway: - tess.c from the sample link Patrick gave crashes as well, so it doesn't seem to be a HOpenGL problem (at least not directly, pls read on) - I also tried the most recent sample bundle (ftp://ftp.sgi.com/opengl), for the fourth edition, same effect - the README for the bundle mentions the need for the CALLBACK macro: "Several programs use callback functions. The method of casting those callback functions worked fine on UNIX based systems, but not on PCs. The programs quadric.c, surface.c, trim.c, tess.c, and tesswind.c have been modified. References to (GLvoid (*)) cast have been removed, and a reference to the CALLBACK type has been added to the declaration of the callback functions. Where CALLBACK is undefined (for instance, in UNIX systems), it is stubbed out by use of #ifndef." - unfortunately, the include files for cygwin/mingw are currently organized in such a way as to undefine CALLBACK on exit, so when I compile tess.c (with CC=gcc -mwindows -mno-cygwin), all the examples using CALLBACK define it as empty (check with gcc -E). This actually leads to comilation warnings about passing the callbacks at incompatible types, and then to segmentation faults at runtime. it just so happens that tess and tesswind are the two examples that use glu callbacks for non-error-recording purposes - I assume some more examples would crash if any errors occured and the error-callbacks were to be used. - replacing the CALLBACK definition in tess.c by the one that was in place in the include files before undefinition (compare the typedef for _GLUfuncptr in the gcc -E output) cures the problem and allows me to compile and run tess without errors or crashes. #ifndef CALLBACK # define CALLBACK __attribute__ ((__stdcall__)) #endif note: this may well be different for post-win98 windows systems, so the "right" way would be to bring the examples and the cygwin/ mingw include files back in sync. don't yet know where to report this.. bug reporting experience anyone? -------------------- 3. so far, so good. but since the HOpenGL version also crashes for the same two examples, I assume that someone got compilation warnings about incompatible type conversions when building the HOpenGL package for windows and didn't notice them, or that the CALLBACK types for different windows versions differ and I get these crashes because I'm compiling the examples on win98 whereas the package was most likely built on winxp..? of course, that's just a guess, and it could be something else, but it isn't a driver problem, and HOpenGL is affected by it. Could anyone please punch a hole into this, or confirm my guess? HOpenGL-FFI-mingw experience, anyone?-) Claus -- C - the portable assembly debugging target

On 2005 Apr 12, Claus Reinke
there are some opengl debuggers and tracers around - I'm googling for a free windows one, mac users seem to have such support provided by apple, other platforms have their own.
Claus, Thank you for the response. I haven't found one yet for XFree86 on FreeBSD. But I did do a number of more experiments. I have a couple of odd results that maybe someone can help with. Here is the strangest one (from my perspective). I've commented which objects can be drawn, and which ones crash. I can't find *any* reason for this behavior, by looking at the code. E.g., Sphere' crashes but Cone draws fine. Looking at the .../GLUT/Objects.hs, the foreign import statements are basically identical for the two functions (Cone takes one extra argument). If anyone can imagine a way that Cone would succeed but Sphere' would fail, I'm all ears. :-) A C program can call glutSolidSphere just fine. Also, I trimmed out every unneeded OpenGL-related call; if I put in the usual boilerplate of setting the projection matrix, etc., it still has the same behavior. -- cut ----------------------------------------------- import Graphics.UI.GLUT import qualified System.Environment as Env main :: IO () main = do objIndex <- getObjIndex createWindow "test" displayCallback $= display objIndex mainLoop display :: Int -> DisplayCallback display objIndex = do renderObject Solid (objects !! objIndex) flush -- comment this out, and it still crashes on 5-6,8-11 -- This is sloppy, sorry... getObjIndex :: IO Int getObjIndex = do args <- Env.getArgs return (intOfFirstArg args) where intOfFirstArg [] = 0 intOfFirstArg (a:_) = read a objects :: [Object] objects = [ Cube 1, -- 0: OK Dodecahedron, -- 1: OK Icosahedron, -- 2: OK Octahedron, -- 3: OK Tetrahedron, -- 4: OK RhombicDodecahedron, -- 5: Crash / user error (freeglut) Sphere' 1 5 5, -- 6: Crash Cone 1 1 5 5, -- 7: OK Cylinder' 1 1 5 5, -- 8: Crash / user error (freeglut) Torus 0.75 1 5 5, -- 9: Crash Teapot 1, -- 10: Crash SierpinskiSponge 1 -- 11: Crash / user error (freeglut) ] -- cut ----------------------------------------------- The "Crash / user error (freeglut)" comment means that those three objects crash with the current GLUT code, but return this error when I "#define GLUT_GET_PROC_ADDRESS_IS_BROKEN 1" in GLUT/cbits/HsGLUT.c: objs: user error (unknown GLUT call glutSolidRhombicDodecahedron, check for freeglut) There's no configure tests which define that - it's not mentioned anywhere else besides HsGLUT.c - so I don't know if that's meaningful, but I thought I would explain it. There's another class of crashes related to lighting & display lists, but this is way too long as it is. I'll stop here, and hope that someone might be able to suggest a reason for the strange behavior. Thanks a lot for reading this far! Tim -- If you're not part of the solution, you're part of the precipitate.

Claus Reinke wrote:
Btw, is there a way to reset the opengl system to a sane state in software? Or are there some invalid assumptions about default state in the other examples?
If OpenGL is getting "stuck" in a non-functional state, that indicates
a bug in the driver.
--
Glynn Clements

[ghc-users removed from cc]
Btw, is there a way to reset the opengl system to a sane state in software? Or are there some invalid assumptions about default state in the other examples?
If OpenGL is getting "stuck" in a non-functional state, that indicates a bug in the driver.
quite possible. but I'm unlikely to get any driver updates for this model:-) still, driver bugs are not uncommon, so one might hope for a function to reinitialize OpenGL soft- and hardware (when workstations became less stable, they moved the reset button from the back to the front;). after all, reboot resets the configuration successfully, so there should be an easier way.. also, it is not completely non-functional, more like partially disabled, eg., after Tess segfault, running BezSurf shows only a black window, but running BezCurve shows the curve without the control points, and Double functions normally.. and as another data-point, if I let Tess segfault within gdb, this partial disabling does not happen at all - the other examples still run normally. if nothing else, HOpenGL should have a chance to contain the effects of this kind of bug on the OpenGL system, just as gdb does. just in case it is not just a driver bug: - I can run just the rectangle or just the triangle, but not just the star - I can run the rectangle, then the triangle, as separate tesselations and displaylists, but not both in one ComplexPolygon - apart from containing the side-effects, gdb bt isn't helping much: gluTessEndPolygon seems to make several nested calls to the older gluEndPolygon, everything else is unknown functions (??) Cheers, Claus sigh.. if today's notebook makers could spell quality-control, I'd have moved on long ago.

Claus Reinke wrote:
Btw, is there a way to reset the opengl system to a sane state in software? Or are there some invalid assumptions about default state in the other examples?
If OpenGL is getting "stuck" in a non-functional state, that indicates a bug in the driver.
quite possible. but I'm unlikely to get any driver updates for this model:-)
still, driver bugs are not uncommon, so one might hope for a function to reinitialize OpenGL soft- and hardware (when workstations became less stable, they moved the reset button from the back to the front;). after all, reboot resets the configuration successfully, so there should be an easier way..
It's the job of the operating system to ensure that there isn't ;)
Less flippantly, the OS (including the driver(s) for the graphics
hardware) are supposed to isolate applications from each other.
If you create a window and use a particular sequence of OpenGL
commands to render into it, you should get the same results regardless
of whether any other processes are using OpenGL concurrently, or
(especially) whether other processes were using it previously.
The OS is effectively reinitialising OpenGL every time it switches
between OpenGL contexts. If that doesn't work when the OS is doing it
implicitly, there's no reason to believe that it would work if the
application did it explicitly.
In short: any problems which persist from one process to another are
definitely due to driver bugs. Problems which only persist for the
lifetime of a single process could be due either to a driver bug or a
bug in the libraries.
In that situation, you can partially re-initialise OpenGL by
discarding the context and creating a new one. But not with GLUT; you
would have to use a toolkit which provides lower-level access, i.e.
the ability to manage contexts explicitly (wglCreateContext() etc).
[Although, with GLUT, you could destroy and re-create the window; I
think that GLUT will create a new context in this case.]
--
Glynn Clements

It's the job of the operating system to ensure that there isn't ;)
configure: checking for OS configure: result: no :) thanks for reminding me that the side-effects of this bug shouldn't persist on a normal system - sometimes I just take this old system too seriously. w98 is not exactly famous for protecting different processes from each other's problems.
If that doesn't work when the OS is doing it implicitly, there's no reason to believe that it would work if the application did it explicitly.
as I mentioned, gdb succeeds on that account, against all reason ;) it is nice that gdb managed to provide the protection usually included in an OS, and I wondered whether HOpenGL could offer the same service. perhaps it isn't worth it, and that part of the problem will die out with w98, but I thought I'd point out the opportunity.
.. driver bugs vs library bugs
appart from the driver/os issue, there does seem to be a library bug in HOpenGL. the C-version of tess exhibits the same symptoms & stack trace, and the fix is simply to add a stdcall attribute to the callback type. So, it seems that HOpenGL on windows/mingw should declare and use the GLU callbacks as stdcall, not ccall (or perhaps use APIENTRY, defined in gl.h?). But I could be wrong about this.. Cheers, Claus In some more detail: from Graphics.Rendering.OpenGL.GLU.Tesselation.hs, an example callback: type BeginCallback' = GLenum -> IO () withBeginCallback :: TessellatorObj -> BeginCallback -> IO a -> IO a withBeginCallback tessObj beginCallback action = bracket (makeBeginCallback (beginCallback . unmarshalPrimitiveMode)) freeHaskellFunPtr $ \callbackPtr -> do setBeginCallback tessObj (marshalTessCallback TessBegin) callbackPtr action foreign import ccall "wrapper" makeBeginCallback :: BeginCallback' -> IO (FunPtr BeginCallback') foreign import CALLCONV unsafe "gluTessCallback" setBeginCallback :: TessellatorObj -> GLenum -> FunPtr BeginCallback' -> IO () the ccall wrapper looks suspicious to me (btw, where is CALLCONV defined?). FunPtr (via Base.Foreign.Ptr.hs) leads to Base.GHC.Ptr.lhs, which defines: -- Function pointers for the default calling convention. data FunPtr a = FunPtr Addr# deriving (Eq, Ord) I'm not sure where to find the details of mapping between this Haskell type and its C equivalent, but if I look in my ghc-installation, I find a file include/HsFFI.h, which defines: typedef void (*HsFunPtr)(void); /* this should better match StgAddr */ This looks precisely like the callback-type that leads the C-version of tess to segfault, because the expected type for GLU callbacks happens to be, from the ghc installation, include/mingw/GL/glu.h: typedef void (APIENTRY *_GLUfuncptr)(); where APIENTRY is defined in include/mingw/GL/gl.h as: #if !defined(APIENTRY) # if defined(__WIN32__) # define APIENTRY __stdcall # else # define APIENTRY # endif #endif Which seems to be the MS version of the gcc variant I tested with tess.c, both variants meaning "callee cleans stack": # define CALLBACK __attribute__ ((__stdcall__)) void CALLBACK beginCallback(GLenum which) Note that, if I understand the "wrapper" idea correctly, HOpenGL requests the callback to be exported as using ccall convention instead.
participants (4)
-
Arjen van Weelden
-
Claus Reinke
-
Glynn Clements
-
Tim Smith