Tue Jul 1 21:06:13 CEST 2008

custodian + custom port

Trying to avoid the creation of zombie processes when custodian shuts
down the gnuplot pipe. This works well with 'close-output-port but
doesn't work with custodians, presumably because the inner port gets
shut down first?

(define (open-gnuplot)
  (let ((co (current-output-port)))
     (process/ports co #f co "gnuplot")
     ((list stdout
       (lambda (bytes start endx _ __)
         (write-bytes bytes stdin start endx))
       (lambda ()
         (printf "closing gnuplot\n")
         (close-output-port stdin)
         (control 'wait)))))))

(define p #f)
(define c (make-custodian))
(parameterize ((current-custodian c))
   (set! p (open-gnuplot)))
(custodian-shutdown-all c)

 Q: does the custodian shut down custom ports?

(define (make-dummy-port)
   (lambda ()
     (printf "closing\n"))))

(define p #f)
(parameterize ((current-custodian c)) (set! p (make-dummy-port)))
(custodian-shutdown-all c)

-> nothing happens..

(close-output-port p)
-> prints "closing\n"

EDIT: solved with double fork using an external utility:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char **argv) {
    int pid;
    if (argc == 1) {
        fprintf(stderr, "usage: %s <prog> <arg> ...\n", argv[0]);
        return -1;
    pid = fork();
    if (!pid) {
        char *a[argc];
        int i;
        for (i=0; i<(argc-1); i++){
            a[i] = argv[i+1];
        a[i] = 0;
        execvp(a[0], a);
        fprintf(stderr, "%s: can't execute %s\n", argv[0], a[0]);
    return 0;