Bug in touchForeignPtr?
simonmar at microsoft.com
Wed Dec 1 06:15:56 EST 2004
On 30 November 2004 16:39, Benjamin Franksen wrote:
> [re-sending because I got no response yet]
> On Tuesday 23 November 2004 13:06, Simon Marlow wrote:
>> On 22 November 2004 17:28, Benjamin Franksen wrote:
>>> However, what I don't understand is why touchForeignPtr is not
>>> honored in my example program: Note that the output text lines from
>>> the finalizers appear *before* the last action in the program (which
>>> is a second getChar). The finalizers *are* called by the GC, and
>>> still the order is wrong.
>> Note that the GC only starts the finaliser thread. The program can
>> still terminate before this thread has run to completion
> I repeat: the program is not yet even near termination when the
> finalizers get executed (in teh wrng order).
> Here is the example program again (with 3 lines added to the end of
> main to illustrate the point):
> import Foreign hiding (newForeignPtr)
> import Foreign.Concurrent
> import System.Mem (performGC)
> type A = ForeignPtr Int
> type B = ForeignPtr Bool
> newA :: IO A
> newA = do
> (pa::Ptr Int) <- malloc
> newForeignPtr pa $ do
> putStrLn "before finalizing A"
> free pa
> putStrLn "after finalizing A"
> newB :: A -> IO B
> newB fpa =
> withForeignPtr fpa $ \pa -> do
> (pb::Ptr Bool) <- malloc
> newForeignPtr pb $ do
> putStrLn "before finalizing B"
> free pb
> putStrLn "after finalizing B"
> touchForeignPtr fpa
> main = do
> a <- newA
> b <- newB a
> putStrLn "Program still not terminated, please hit <enter> again!"
> putStrLn "Program termination will now be initiated."
> And this is the output:
> franksen at linux: .../foreigntouchbug > ./a.out
> before finalizing A
> after finalizing A
> before finalizing B
> after finalizing B
> Program still not terminated, please hit <enter> again!
> Program termination will now be initiated.
The GC simply found that both objects were unreferenced and hence ran
their finalizers, in no particular order. The fact that B referred to A
has no effect, since both objects were unreachable from the roots. If B
had been reachable, then A would not have been finalized - this is the
only way in which the ordering would have shown up.
This is just a manifestation of the lack of ordering between finalizers
- sorry if I wasn't clear before. The documentation will be updated for
the 6.4 release to more closely reflect the state of affairs.
More information about the Glasgow-haskell-users