[GHC] #13730: Running GLUT code in GHCi yields NSInternalInconsistencyException
GHC
ghc-devs at haskell.org
Tue May 23 06:57:55 UTC 2017
#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
More information about the ghc-tickets
mailing list