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)

> Oh. Well, it wouldn't make things much worse if finalizers were run
> concurrently. I would have to wrap g_object_unref in a function that
> acquires a global lock, but that's all.
> Why is this not done?

The GC only runs in parallel when there is a +RTS -N<n> option, so even 
if it were capable of running finalizers concurrently you wouldn't 
notice anything until you used +RTS -N<n>.  But running in parallel is 
not the goal here: we want concurrency, not parallelism.

The technical reason that we don't run finalizers concurrently is 
because in order to decide which finalizers can be run, we have to 
complete the GC traversal, which means all GC threads have stopped. 
Given that all GC threads have already stopped, it would be extra work 
to start them up again to run finalizers, so instead we just run the 
finalizers sequentially in the main GC thread.

>> 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.

> As it stands, I can already implement what you suggest above: I replace
> each call of the GC to g_object_unref with a function that enqueues the
> finaliasation task into the Gtk+ queue.

Right.  Or if that's too inefficient, use a separate queue and add 
something to the Gtk+ main loop that runs the items in that queue.

> 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? 
  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.

>> 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.

>> 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.

 > It
> seems easier to me now than before, when I though the GC would execute
> finalizers concurrently rather than enqueuing them in a list. It would
> be ok to associate a ForeignPtr with a Haskell thread id (which in turn
> is bound to the right OS thread). You could keep a list of finalizers on
> a per-thread-id basis and add a process that executes these finalizers
> into the running queue of that thread. With this approach, it wouldn't
> matter that the associated OS thread is currently running in C land.
>
> I'm probably naive about the complexity of this approach, but what I
> would implement in Gtk2Hs would boil down to something similar but be
> much more restricted.
>
> Maybe you could elaborate on your idea again. I'm pretty sure I do not
> understand the details of your proposal.

Hopefully I've explained it well enough, if not please let me know!

Cheers,
        Simon

(gdb) where
#0  0x0000003c0aa0af19 in pthread_cond_wait@@GLIBC_2.3.2 () from 
/lib64/libpthread.so.0
#1  0x00000000005b2c0e in waitCondition (pCond=0x1a43918, 
pMut=0x1a43948) at posix/OSThreads.c:65
#2  0x00000000005d72d9 in waitForReturnCapability (pCap=0x7ffffe1499f0, 
task=0x1a438e0) at Capability.c:445
#3  0x00000000005a5934 in rts_lock () at RtsAPI.c:572
#4  0x00000000004cf247 in SystemziGlibziGObject_d1wV ()
#5  0x0000003c10cd8eed in ?? () from /usr/lib64/libgtk-x11-2.0.so.0
#6  0x0000003c0ba0d6a8 in g_object_unref () from /lib64/libgobject-2.0.so.0
.... various stuff omitted ....
#41 0x0000003c0ba0d632 in g_object_unref () from /lib64/libgobject-2.0.so.0
#42 0x00000000005b20fd in runCFinalizer (fn=0x408968, ptr=0x1a69440, 
env=0x0, flag=0) at Weak.c:34
#43 0x00000000005b216a in runAllCFinalizers (list=0x2afbacb5f060) at 
Weak.c:50
#44 0x00000000005a8077 in hs_exit_ (wait_foreign=rtsFalse) at 
RtsStartup.c:413
#45 0x00000000005a81a8 in shutdownHaskellAndExit (n=0) at RtsStartup.c:557
#46 0x00000000005a4c6a in real_main () at Main.c:144
#47 0x00000000005a4ca4 in main (argc=5, argv=0x7ffffe14b338) at Main.c:156


------------------------------------------------------------------------------
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