On Tue, 2009-11-10 at 13:13 +0000, Simon Marlow wrote:
> On 04/11/2009 18:31, Axel Simon wrote:
> 
> > I just realized that we haven't changed everything to use direct calls
> > to C finalizers but to Haskell finalizers. I assume that this is because
> > Haskell still got called from within the GC. If it is still called from
> > within the GC, then some signals are being emitted as a result of
> > finalizing an object. I probably need an example where this goes wrong.
> > I don't know if it is possible to run the Haskell program in gdb and get
> > a traceback of the C functions that called Haskell during GC. However,
> > it might just be a very plain bug in that we bound a function as
> > 'unsafe' when, in fact, it may trigger a callback to Haskell.
> 
> Does the traceback in my original message give you enough information? 
> (reproduced at the end of this message)

Well, you omitted 'various' stuff. I agree that something is calling
back into C when it shouldn't. Are there any function names between
frame 6 and 44 that would give me a clue where we've been negligent?

[..]

> >> I suggest that the C finalizers should be very simple: just add the
> >> tasks to be done onto a queue protected by a mutex, and have the main
> >> loop process the queue. The mutex is necessary not to protect against
> >> multiple finalizers running concurrently, but to protect against
> >> finalizers running concurrently with foreign calls (e.g. the gtk main
> >> loop).
> >>
> >> This sounds like what you proposed above, and in order to make this
> >> work the GC needs to inform the main loop when more finalizers have
> >> been added. I'm not sure of the best way to do this.
> >
> > I'm not quite following: who is in charge of this list? The GC?
> 
> No, this would be completely managed by gtk2hs and its finalizers.

Ok, I can keep a queue in C land for this, no prob.

[..]
> > As I said, the problems with this is that I cannot guarantee that the
> > application program will every run the Gtk main loop. I can only
> > guarantee that in real GUI programs, not in those that use Gtk2Hs to
> > render some graphics into a file. Since the problems only really occur
> > when objects with handles to Xlib or Win32 are finalized this would be a
> > solution and is implementable without any change to ghc. I'm just weary
> > that there is some object whose finalizer I do not enqueue in the main
> > Gtk loop and which for some reason calls either Xlib/Win32 or Haskell.
> 
> In any program that uses gtk2hs/cairo/whatever there must be a single 
> distinguished thread that is allowed to perform GUI operations, correct? 

No, unfortunately not. Once we've cabalised the parts of Gtk2Hs, it is
perfectly reasonable to build programs without GUI, say using Cairo to
create PDFs. However, Cairo (and other non-GUI sub-libaries in Gtk2Hs)
can cope with other threads calling g_object_unref. Now, g_object_unref
is thread-safe and hence, the current way of directly caling
g_object_unref from the GC is perfectly fine.

>   So the task is just to arrange somehow that it is possible to 
> communicate with that thread that it has some finalization actions to 
> perform.  I'm not sure how you do that, but I'm not really familiar with 
> the structure of these kinds of applications.

Yes, for the GUI part of Gtk2Hs, this is the only way to go. I think
what I would like is a hook in the RTS of ghc that allows me to run a C
function each time the GC has finished. This C function can be run from
any OS thread. I would make this function call g_idle_add (which is
thread-safe) to add a function that empties the list of finalizers that
I've accumulated during GC. If the main Gtk+ loop is currently running
or will run at some point in the future, the finalizers form the list
will be executed. If the Gtk+ is never run again then I probably don't
care anyway that the finalizers are not run since the program is stuck
or about to end.

> >> I wonder if for the time being you should just revert to using Haskell
> >> finalizers. They are less efficient and prompt, but they do support
> >> proper synchronisation.
> >
> > It seems I'm using Haskell finalizer. So you might just have observed an
> > unsafe/safe declaration bug in Gtk2Hs. However, the Xlib warning is the
> > real thing that cannot so easily be worked around.
> 
> If you consistently use Haskell finalizers, and the finalizers always 
> use idleAdd, then you can avoid all these problems for now, at the 
> expense of some performance.
> 
> But there is evidence that gtk2hs is not using Haskell finalizers, or at 
> least not consistently: see the gdb backtrace below.

We certainly do not call g_idle_add to run the finalizer the objects. We
do it immeditely, thereby triggering the occasional callback to Haskell
or a call to Xlib/Win32 which is likely to crash the program. We can fix
this using the queue/list approach.

> >> Can I suggest that first of all there should be a warning on the
> >> gtk2hs page and in the documentation about the use of -threaded; if
> >> I'd known that it wasn't currently supported I would have avoided it.
> >
> > Yes, I agree, we're not very upfront about this...
> 
> Thanks for the blog post!
> 
> >> Secondly, I'm happy to help here. I think we ought to have
> >> multi-threaded GUI support, and it's worth putting in some effort to
> >> make it work. Let me know how you'd like to proceed.
> >
> > Could you say why it is so hard to associate a finalizer with a thread
> > id and ensure that the finalizer is run from that particular thread?
> 
> Suppose that hypothetically it was possible to say that a finalizer must 
> be run by the main thread.  How should the runtime arrange to do it? 
> The main thread is currently inside a call to the Gtk main loop, and the 
> only way to get it out is to do idleAdd (or similar), but that is 
> specific to gtk2hs; there's no general way to do this, so there's no 
> general mechanism I can add to the RTS.
> 
> Perhaps you want to create a Haskell thread to run the finalizer, but 
> keep track of the fact that this Haskell thread can only be run by the 
> main OS thread.  There might be no fundamental problem with this scheme, 
> but it would require deep restructuring of the RTS to make it possible: 
> currently you can associate a Haskell thread with an OS thread 
> one-to-one, but this would make a many-to-one mapping.  And I'm not sure 
> it's exactly what you want, because you still have to arrange that the 
> gtk main loop returns to Haskell occasionally, so you're not really 
> getting the benefit of -threaded; it's better to just use idleAdd in the 
> first place, which requires no extra support in the RTS, and does 
> essentially the same thing.

Oh, I think I understand our different perception of what we want. The
main loop of Gtk+ will always return at some point. Thus, all I was
asking is that the Haskell GC should keep a per-OS-thread list of
finalizers to run and *only* if the GHC runtime has this OS thread
avaiable to itself, it would run the associated finalizers.

Thus, I thought adding thread-bound finalizers would be as easy as
adding a function to the running queue of the Haskell thread that is
associated with the OS thread of the finalizer.

So I can see two ways forward:

(1) a hook in GHC to install a C function that is run by the RTS after
each GC. The RTS may call this function from any thread.

(2) have a new Finalizer type that takes an OS thread id. If this
finalizer is due to be run, the GC enqueues it into running queue of the
Haskell thread that is bound to the OS thread. The finalizer then has to
be called using a 'safe' call, so that the finalizer may call back into
Haskell land.

(1) is easier for you, (2) for me. If there's no other libraries that
have these kind of threading problems, then maybe (1) is enough.

Let me know if I was clear/correct.

Cheers,
Axel.



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Gtk2hs-devel mailing list
Gtk2hs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel

Reply via email to