Question

When a wxHaskell GUI is started and closed, and then another wxHaskell GUI is started again, the application gets segmentation fault due to stack overflow.

Simple demonstration source:

module Main where

import Graphics.UI.WX

main = do
  start $ frame []
  start $ frame []

It seems this is an old bug, see http://permalink.gmane.org/gmane.comp.lang.haskell.wxhaskell.general/789. This message has a link to an issue at wxHaskell's SourceForge repository, and a much more recent comment there mentions a version of wxHaskell (development branch for wxWidgets 2.9, it seems) which has no bug.

I am using Ubuntu 12.04 with wxWidgets 2.8, and so I have to use wxHaskell 0.13. I tried to find any information about this bug by looking through changelog of supposedly working development version, but couldn't find anything.

Can this buggy behaviour be fixed for wxHaskell 0.13, or at least is it possible to make some sort of workaround? Rewriting application to work with one persistent GUI seems unnecessary complex.

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top