[gambit-list] How to save s-expressions

Marc Feeley feeley at iro.umontreal.ca
Sun Oct 28 09:11:31 EDT 2012

Le 2012-10-27 à 8:11 PM, Mikael <mikael.rcv at gmail.com> a écrit :

> Marc,
> Do all ports GC? (am thinking especially about file and tcp client and server ports)

Yes.  For all ports, the OS ressources which are attached to a port are freed (including closing file descriptors) when the port is GCed.

> I suppose that the fact that with-*-port closes the port on finalization cannot be relied on to always work, because what if there's an exception during the thunk's execution and it's handled in a way that never leaves control back, or the thread is thread-terminate!:d (could happen a dynamic-wind finalizer would not be trigged right)?

Yes.  If you need to force closing a file descriptor then you need to catch exceptions and explicitly close the port.

Here's a small program you can use to test limits on your particular OS.

;; File: fd-autoclose.scm

(define (on-gc thunk)
  (make-will (cons 1 2) ;; garbage
             (lambda (obj) (thunk) (on-gc thunk))))

(define counter 0)

(on-gc (lambda () (pp counter) (set! counter 0)))

 (lambda (e)
   (display-exception e))
 (lambda ()
   (let loop ((n 5000))
     (if (> n 0)
           (set! counter (+ counter 1))
           (let ((port (open-tcp-client "localhost:22")))
             (loop (- n 1))))))))

It will try to open 5000 TCP connections in a loop, relying on the GC to close the connections.  The program displays the number of connections that were open (and closed) since the last garbage collection.  If the heap size is small, then the file descriptors never run out.  But if a large heap is used, the program will reach the OS limit on the number of open file descriptors.

Here's a test on an OS X machine:

% gsi -:d2 fd-autoclose.scm 
*** GC: 0 ms, 180K alloc, 203K heap, 37.1K live (18% 18528+19448)
*** GC: 0 ms, 347K alloc, 209K heap, 60.4K live (29% 36752+25140)
*** GC: 1 ms, 495K alloc, 209K heap, 60.4K live (29% 36752+25140)
*** GC: 1 ms, 644K alloc, 209K heap, 60.4K live (29% 36752+25140)
*** GC: 5 ms, 792K alloc, 209K heap, 60.4K live (29% 36752+25140)
...etc, until the normal end of the program (note the small 209 KB heap)

and with a 19 MB heap the program works properly:

% gsi -:d2,m19000 fd-autoclose.scm 
*** GC: 78 ms, 19.0M alloc, 18.6M heap, 63.4K live (0% 37696+27248)
*** GC: 45 ms, 37.5M alloc, 18.6M heap, 63.4K live (0% 37696+27248)

but with a 20 MB heap the program terminates with an error:

% gsi -:d2,m20000 fd-autoclose.scm 
*** GC: 73 ms, 19.4M alloc, 19.9M heap, 60.3K live (0% 36600+25140)
Too many open files
(open-tcp-client "localhost:22")

It would seem that the maximum number of open file descriptor on this machine is about 2560 (considering a few file descriptors are open for stdin, stdout, ...).


More information about the Gambit-list mailing list