
#13730: Running GLUT code in GHCi yields NSInternalInconsistencyException --------------------------------+---------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.0.2 Resolution: | Keywords: Operating System: MacOS X | Architecture: Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | --------------------------------+---------------------------------------- Comment (by svenpanne): Hmmm, taking a step back, the author of a `foreign import` has to answer the following questions: * Is it OK for the foreign call that (part of) it might run in another OS thread? * Can the foreign call block? * Can the foreign call cause a GC? The last item is probably the same question as: Can the foreign call call back into Haskell? For OpenGL-related calls the answers are: * All OpenGL-related code **must** run in a single thread. There is some arcane Kung Fu in newer OpenGL revisions to allow a bit of multithreading, but it is rarely used and must be done in an explicit manner. * The vast majority of OpenGL calls can't block, and even if they can: Due to the single thread requirement above, it is OK to block everything. * More recent OpenGL versions have the a facility to register debugging callbacks which can fire at any time, so basically all OpenGL calls can cause a GC. All OpenGL calls are done dynamically via native function pointers, something like: {{{#!haskell foreign import ccall "dynamic" dyn376 :: FunPtr (Ptr a -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ()) -> Ptr a -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO () }}} `safe` is the default, so this should be correct. The GLUT binding is basically implemented the same way, with the same restrictions imposed by the native API. So the bug IMHO in GHCi is that it somehow silently does some thread switches behind the scenes, although the original program did not talk about multithreading at all. Requiring `runInBoundThread` here doesn't seem right. I think part of the confusion in this ticket and #8281 is that it is highly unclear what `safe` and `unsafe` should actually mean nowadays. In the old days, `safe` just meant "Hey, I can call back into Haskell land, better take care of your data structures for GC etc.". I have no idea what it is supposed to mean in detail today, but it definitely shouldn't be a license for thread migration. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13730#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler