Bug in touchForeignPtr?

Simon Marlow 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
>   getChar
>   performGC
>   getChar
>   putStrLn "Program still not terminated, please hit <enter> again!"
>   getChar
>   putStrLn "Program termination will now be initiated."
> 
> And this is the output:
> 
> franksen at linux: .../foreigntouchbug > ./a.out
> <enter>
> before finalizing A
> after finalizing A
> before finalizing B
> after finalizing B
> <enter>
> Program still not terminated, please hit <enter> again!
> <enter>
> 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.

Cheers,
	Simon


More information about the Glasgow-haskell-users mailing list