A workaround for the bug can be devised, at least for wxWidgets-2.8 and GTK.
It seems, unfortunately, that wxHaskell developers did not manage to implement GUI starting interface as a reentrant one. On each GUI start wxHaskell calls wxWidgets in such a way that a method wxApp::Initialize from wxWidgets source file src/gtk/app.cpp is called. In particular, this method executes following two lines to initialize GTK event loop for wxWidgets:
wxgs_poll_func = g_main_context_get_poll_func(NULL);
g_main_context_set_poll_func(NULL, wxapp_poll_func);
The problem is that while on first GUI start wxgs_poll_func
is set to whatever poll function GTK starts with (seems to be g_poll
), on second GUI start wxgs_poll_func
is set to wxapp_poll_func
— on first GUI start we set wxapp_poll_func
as GTK poll function, and when we ask for it on the second GUI start using g_main_context_get_poll_func
, we get wxapp_poll_func
back.
This backfires during execution of wxapp_poll_func
, which, as far as I understand, is supposed to call any poll function used by GTK before the wxWidgets is initialized by calling wxgs_poll_func
. On first GUI start it actually calls the poll function GTK starts with, but on second GUI start it calls itself, going into infinite recursion and causing stack overflow.
The rather hackish workaround is to manually reset g_poll
as GTK poll function after each GUI session. This can be accomplished using following C function:
#include <glib.h>
void reset_g_poll()
{
g_main_context_set_poll_func(NULL, g_poll);
}
Compile it as shared library and import it as C foreign function, and properly modified demo works. Modified demo:
module Main where
import Graphics.UI.WX
foreign import ccall unsafe "reset_g_poll"
reset_g_poll :: IO ()
main = do
start $ frame []
reset_g_poll
start $ frame []
reset_g_poll