[Haskell-cafe] gtk2hs and runghc
Duncan Coutts
duncan.coutts at worc.ox.ac.uk
Wed Sep 23 16:12:25 EDT 2009
On Wed, 2009-09-23 at 20:24 +0200, Günther Schmidt wrote:
> >> No, but you can unsafeInitGUIForThreadedRTS.
> >
> > If you observe the foot-shooting restrictions (of which the easiest is
> > to not use forkIO).
> >
> And exactly herein lies the problem :)
>
> I've seen your response to the recent post about gui state, in which you
> mention your own prefered solution to the problem, ie. that you "post"
> your state to a channel which is read in a thread.
>
> I'm doing the same thing, but I'm also "calling" gui code from within that
> thread.
> I figured since the thread itself isn't a separate OS thread it
> shouldn't be a problem.
Stop! You are confused about the relationship between Haskell threads
and OS threads.
By default you have _no_ control over which OS thread your Haskell
threads run on. Using forkIO provides no promises at all about that.
Using forkOS provides the opposite guarantee to the one you want. There
is no API to launch a Haskell thread and guarantee that runs on the same
OS thread as some existing Haskell thread.
(One way is to use the single-threaded rts)
The documentation for unsafeInitGUIForThreadedRTS states:
If you want to use Gtk2Hs and the threaded RTS then it is your
obligation to ensure that all calls to Gtk+ happen on a single
OS thread. If you want to make calls to Gtk2Hs functions from a
Haskell thread other than the one that calls this functions and
mainGUI then you will have to 'post' your GUI actions to the
main GUI thread. You can do this using postGUISync or
postGUIAsync.
The postGUI actions do some magic so that your IO actions are run on the
same OS thread as the GUI is running on.
> It seems to work once the app is compiled, but running the code in either
> ghci or with runghc it crashes.
Right, because when you compile it you are using the single threaded rts
but if you linked using -threaded or if you use ghci or runghc then you
are using the threaded rts.
There are two solutions:
1. use the single threaded rts
2. annotate all sequences of GUI calls with postGUISync or
postGUIAsync so that they get run in the GUI thread and not some
random thread.
The first is obviously much easier. Only go with the second if for some
reason you actually need the -threaded rts.
There is no claim that the second option is a good GUI programming
model. The Gtk2Hs developers added the possibility of running on the
threaded rts due to popular demand but the intention of the
reallyLongNamedFunction unsafeInitGUIForThreadedRTS is to make you stop
and think about what you are doing :-).
Perhaps we should make it even more so, like
unsafeInitGUIIHaveReadTheDocsAndIAmSureIAmNotGoingToShootMyselfInTheFoot
Duncan
More information about the Haskell-Cafe
mailing list