
Hi, I have encountered a weird behavior of ForeignPtr. I want to know how to work around this. I am using GHC 6.6.1 on Darwin. [1] Foreign.Concurrent The following code prints "called" when it is linked with -threaded RTS, but it prints nothing when it isn't. import Foreign.Marshal.Alloc import qualified Foreign.Concurrent as Conc main = do mem <- mallocBytes 10 Conc.newForeignPtr mem $ print "called" [2] Foreign.ForeignPtr The following code prints nothing when it isn't linked with -threaded RTS, but when it is, it *sometimes* prints "called" but not always. import Foreign.Marshal.Alloc import Foreign.Ptr import Foreign.ForeignPtr foreign import ccall "wrapper" mkFinalizer :: (Ptr () -> IO ()) -> IO (FunPtr (Ptr () -> IO ())) main = do mem <- mallocBytes 10 fin <- mkFinalizer $ \ _ -> print "called" newForeignPtr fin mem _______________________________________________________ - PHO - http://ccm.sherry.jp/ OpenPGP public key: 1024D/1A86EF72 Fpr: 5F3E 5B5F 535C CE27 8254 4D1A 14E7 9CA7 1A86 EF72

Hello PHO, Sunday, July 22, 2007, 5:36:27 PM, you wrote:
[2] Foreign.ForeignPtr
The following code prints nothing when it isn't linked with -threaded RTS, but when it is, it *sometimes* prints "called" but not always.
import Foreign.Marshal.Alloc import Foreign.Ptr import Foreign.ForeignPtr
foreign import ccall "wrapper" mkFinalizer :: (Ptr () -> IO ()) -> IO (FunPtr (Ptr () -> IO ()))
main = do mem <- mallocBytes 10 fin <- mkFinalizer $ \ _ -> print "called" newForeignPtr fin mem
try to add performGC at end - this should force collecting garbage and therefore printing of string. otherwise, it's ok - there is no guarantee that GC will be performed and therefore that you finalizer will be performed. it's rather stanard behavior for GC languages - finalizers are almosr useless there -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

From: Bulat Ziganshin
try to add performGC at end - this should force collecting garbage and therefore printing of string. otherwise, it's ok - there is no guarantee that GC will be performed and therefore that you finalizer will be performed. it's rather stanard behavior for GC languages - finalizers are almosr useless there
So I changed the code like this but the result was exactly the same. The documentations of both Foreign.ForeignPtr (*1) and Foreign.Concurrent (*2) say "The only guarantee is that the finalizer runs before the program terminates." So I expected the finalizer to be called. import Foreign.Marshal.Alloc import Foreign.Ptr import Foreign.ForeignPtr import System.Mem import qualified Foreign.Concurrent as Conc main = work >> performGC where work = do mem <- mallocBytes 10 Conc.newForeignPtr mem $ print "called" *1: http://haskell.org/ghc/docs/latest/html/libraries/base/Foreign-ForeignPtr.ht... *2: http://haskell.org/ghc/docs/latest/html/libraries/base/Foreign-Concurrent.ht... _______________________________________________________ - PHO - http://ccm.sherry.jp/ OpenPGP public key: 1024D/1A86EF72 Fpr: 5F3E 5B5F 535C CE27 8254 4D1A 14E7 9CA7 1A86 EF72

On Mon, Jul 23, 2007 at 11:07:40AM +0900, PHO wrote:
same. The documentations of both Foreign.ForeignPtr (*1) and Foreign.Concurrent (*2) say "The only guarantee is that the finalizer runs before the program terminates."
That's a documentation bug. In the HEAD it says: newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a) -- ^Turns a plain memory reference into a foreign pointer, and -- associates a finaliser with the reference. The finaliser will be executed -- after the last reference to the foreign object is dropped. Note that there -- is no guarantee on how soon the finaliser is executed after the last -- reference was dropped; this depends on the details of the Haskell storage -- manager. Indeed, there is no guarantee that the finalizer is executed at -- all; a program may exit with finalizers outstanding. (This is true -- of GHC, other implementations may give stronger guarantees). Thanks Ian

From: Ian Lynagh
That's a documentation bug. In the HEAD it says:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a) -- ^Turns a plain memory reference into a foreign pointer, and -- associates a finaliser with the reference. The finaliser will be executed -- after the last reference to the foreign object is dropped. Note that there -- is no guarantee on how soon the finaliser is executed after the last -- reference was dropped; this depends on the details of the Haskell storage -- manager. Indeed, there is no guarantee that the finalizer is executed at -- all; a program may exit with finalizers outstanding. (This is true -- of GHC, other implementations may give stronger guarantees).
Uh, ok... Thank you for your information. _______________________________________________________ - PHO - http://ccm.sherry.jp/ OpenPGP public key: 1024D/1A86EF72 Fpr: 5F3E 5B5F 535C CE27 8254 4D1A 14E7 9CA7 1A86 EF72
participants (3)
-
Bulat Ziganshin
-
Ian Lynagh
-
PHO