Re: Proposed change to ForeignPtr
Malcolm Wallace wrote [snip]
Quite simply, no finaliser (whether in Foogle or Haskell) should be capable of triggering a garbage collection within its call. This condition is absolutely necessary to prevent a cascade effect of cross-language garbage collections, where a finaliser in Haskell could trigger a GC in Foogle which triggers another (nested) GC in Haskell etc. [snip] Unfortunately some sort of cascade is exactly what we want and need when the Haskell finaliser indicates that Haskell is no longer interested in some Foogle object, which means Foogle can run a GC which indicates Foogle is no longer interested in some Haskell object and so on . . .
Thus, if Haskell.freeSomething calls Foogle.freeSomething, and Foogle.freeSomething cannot cause a Foogle GC, then no Foogle finalisers are run yet, and so Foogle *cannot* call the Haskell world until the Haskell GC is complete. After that, it doesn't matter when the Foogle finaliser decides to run. [snip] But surely Foogle has no way of knowing when the Haskell GC is over? Suppose Haskell does
[enter GC] ... [run finaliser 1] ... [run finaliser 2] ... [leave GC] Then you want Foogle to delay any Haskell calls consequent on finaliser 1 until [leave GC], don't you? How can it? Is it really so difficult to create some queue of delayed functions which can be appended to from C and which nhc checks every time it does "leave GHC"?
George Russell wrote: [snip]
Is it really so difficult to create some queue of delayed functions which can be appended to from C and which nhc checks every time it does "leave GHC"? [snip] Sorry, that was rather impolite of me. Now I've looked back through the archives I see that Malcolm has tried this and found it difficult for good reason. All the same I don't see how it can be avoided. In Foogle-land they can't know anything about when Haskell is running a garbage collection or not, and of course Foogle might be running various concurrent threads (just like Haskell), so if you are going to say that Foogle is never to call a Haskell function during a Haskell garbage collection, I don't see how Foogle is to call Haskell at all.
George Russell <ger@tzi.de> writes:
Unfortunately some sort of cascade is exactly what we want and need when the Haskell finaliser indicates that Haskell is no longer interested in some Foogle object, which means Foogle can run a GC which indicates Foogle is no longer interested in some Haskell object and so on . . .
Yes. The key thing is just to delay the steps of the cascade so that you are not trying to call Haskell/Foogle code whilst there is no Haskell/Foogle heap available to run it.
After that, it doesn't matter when the Foogle finaliser decides to run.
But surely Foogle has no way of knowing when the Haskell GC is over?
When sequential control returns to the Foogle world, that is when the Haskell GC is guaranteed to be complete.
Suppose Haskell does
[enter GC] ... [run finaliser 1] ... [run finaliser 2] ... [leave GC]
Then you want Foogle to delay any Haskell calls consequent on finaliser 1 until [leave GC], don't you? How can it?
Because the Haskell calls don't happen until the Foogle GC invokes them. Ok, you have a Haskell ForeignPtr which is really a Foogle object. It becomes garbage. At the next Haskell GC, its finaliser is run. The finaliser is not Haskell code. The finaliser is Foogle code. This finaliser runs and a Haskell StablePtr contained within the Foogle object becomes garbage. Although the Haskell object is regarded as a StablePtr in Haskell land, it is a Foogle ForeignPtr. Hence, its finaliser does not run yet. The Haskell GC finishes. Computation proceeds. At some later moment, Foogle exhausts its heap and starts a GC. The finaliser for the garbage object is now run. This is not Foogle code, it is Haskell code. In fact, it is the Haskell routine freeStablePtr. This is ok, because we have sufficient heap to run the finaliser. The StablePtr is released. The Foogle GC finishes. Computation proceeds.
Is it really so difficult to create some queue of delayed functions which can be appended to from C and which nhc checks every time it does "leave GC"?
I did implement this, once. The problem is that we don't know when to run the delayed finaliser. The moment Haskell GC finishes is *not* a good time. Some arbitrary reduction step is in mid-progress, and running another process at this moment corrupts the context. What you really need is some kind of scheduler that can decide when it is safe to run an independent thread. Regards, Malcolm
participants (2)
-
George Russell -
Malcolm Wallace