Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] GC and file descriptors
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Mikael Brockman <phubuh@p...>
Subject: Re: [Caml-list] GC and file descriptors
On Thu, 2003-11-13 at 20:47, Dustin Sallings wrote:
> On Nov 13, 2003, at 6:24, Mikael Brockman wrote:
> 
> > \If the in_channel is heap allocated, you can do
> >
> >   let close o = ignore (Unix.close_process_in o)
> >
> >   let open_process_in str =
> >     let r = Unix.open_process_in str in
> >       Gc.finalise close r;
> >       r
> >
> >   let tput x =
> >     let buf = String.create 8 in
> >       String.sub buf 0 (input (open_process_in ("tput " ^ x)) buf 0 8)
> >
> > If it is not, you could probably create a wrapper type that has to be
> > heap allocated.
> 
> 	That's very interesting.  You answered some questions, but brought up 
> some new ones.  Are there things that are not heap allocated, and how 
> will I recognize these?

Yes, there are values that are not heap allocated.  The Gc manual has
this to say:

> Some examples of values that are not heap-allocated are integers,
> constant constructors, booleans, the empty array, the empty list, the
> unit value. The exact list of what is heap-allocated or not is
> implementation-dependent. Some constant values can be heap-allocated
> but never deallocated during the lifetime of the program, for example
> a list of integer constants; this is also implementation-dependent.
> You should also be aware that compiler optimisations may duplicate
> some immutable values, for example floating-point numbers when stored
> into arrays, so they can be finalised and collected while another copy
> is still in use by the program.

I think it is pretty safe to assume that objects are heap allocated, so
if the function passing idiom suggested earlier is insufficient, you can
wrap the Unix process in an object that sets a finalizer in
initialization.

  let close_unix_process o =
    prerr_endline "closing unix process";
    ignore (o#close ())

  class unix_process cmd =
  object (self)
    val stream = Unix.open_process_in cmd

    initializer
      Gc.finalise close_unix_process self
  
    method input = input stream
    method close () = Unix.close_process_in stream
  end

  let read_some proc =
    let buf = String.create 2048 in
      String.sub buf 0 (proc#input buf 0 2048)

> # read_some (new unix_process "ls /");;
> - : string =
> "bin\nboot\ndev\netc\nhome\nlib\nmnt\nproc\nroot\nsbin\ntmp\nusr\nvar\n"
> # Gc.full_major ();;
> closing unix process
> - : unit = ()
> #

Also, I don't think the default signal handler for SIGKILL forces a major
cycle, but that's easily fixed with Sys.signal or Sys.set_signal.

--
Mikael Brockman
<phubuh@phubuh.org>

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners