Next: , Previous: , Up: posix process fork   [Index]


4.6.2.3 Preparing binary input/output ports

Function: fork-with-binary-ports parent-proc child-thunk

Wrapper for fork that sets up the file descriptor pipes and binary input/output ports to communicate with the child process, fork. When successful: return the same return value of fork; otherwise raise the same exception of fork.

The procedure parent-proc is called as follows:

(parent-proc child-pid
             parent->child-stdin
             parent<-child-stdout
             parent<-child-stderr)

where the arguments are the following objects:

child-pid

It is a fixnum representing the pid of the child process.

parent->child-stdin

It is a binary output port writing into the standard input of the child process.

parent<-child-stdout

It is a binary input port reading from the standard output of the child process.

parent<-child-stderr

It is a binary input port reading from the standard error of the child process.

The thunk child-thunk is called with no arguments. The child can use the standard ports returned by standard-input-port, standard-output-port, standard-error-port which are made to wrap standard file descriptors distinct from the parent’s standard file descriptors.

Function: after-fork/prepare-child-binary-input/output-ports

To be called in the child process, after a fork operation and after calling after-fork/prepare-child-file-descriptors to prepare binary input and output ports wrapping the standard file descriptors. Return 3 values:

  1. Binary input port reading from the standard file descriptor 0. It is the port returned by standard-input-port.
  2. Binary input port writing to the standard file descriptor 1. It is the port returned by standard-output-port.
  3. Binary input port writing to the standard file descriptor 2. It is the port returned by standard-error-port.
Function: after-fork/prepare-parent-binary-input/output-ports parent->child-stdin parent<-child-stdout parent<-child-stderr

To be called in the parent process, after a fork operation, to build Scheme input and output binary ports around standard file descriptors for the child process. The arguments are:

parent->child-stdin

It must be a file descriptor that writes in the standard input of the child process.

parent<-child-stdout

It must be a file descriptor that reads from the standard output of the child process.

parent<-child-stderr

It must be must be a file descriptor that reads from the standard error of the child process.

Return 3 values:

  1. Binary output port that writes in the standard input of the child process. Closing this port will also close the underlying file descriptor.
  2. Binary input port that reads from the standard output of the child process. Closing this port will also close the underlying file descriptor.
  3. Binary input port that reads from the standard error of the child process. Closing this port will also close the underlying file descriptor.

Here is an example that forks a process, sets up the file descriptors in the child process, sets up binary ports in both the parent and the child, waits for child to terminate.

(import (vicare)
  (prefix (vicare posix) px.))

(let-values
    (((child-stdin          parent->child-stdin) (px.pipe))
     ((parent<-child-stdout child-stdout)        (px.pipe))
     ((parent<-child-stderr child-stderr)        (px.pipe)))

  (define (parent-proc child-pid)
    (px.close child-stdin)
    (px.close child-stdout)
    (px.close child-stderr)
    (receive (child-stdin child-stdout child-stderr)
        (px.after-fork/prepare-parent-binary-input/output-ports
             parent->child-stdin
             parent<-child-stdout
             parent<-child-stderr)
      (unwind-protect
          (let ((bufout (make-bytevector 4 0))
                (buferr (make-bytevector 4 0)))
            (put-bytevector child-stdin '#ve(ascii "ciao\n"))
            (flush-output-port child-stdin)
            (let ((status (px.waitpid child-pid 0)))
              (if (and (px.WIFEXITED status)
                       (zero? (px.WEXITSTATUS status)))
                  (begin
                    (get-bytevector-n! child-stdout bufout 0 4)
                    (get-bytevector-n! child-stderr buferr 0 4)
                    (values bufout buferr))
                (error #f
                  "child process exited abnormally"
                  status))))
        (close-output-port child-stdin)
        (close-input-port  child-stdout)
        (close-input-port  child-stderr))))

  (define (child-thunk)
    (guard (E (else
               (print-condition E)
               (exit 1)))
      (px.close parent->child-stdin)
      (px.close parent<-child-stdout)
      (px.close parent<-child-stderr)
      (px.after-fork/prepare-child-file-descriptors
          child-stdin child-stdout child-stderr)
      (receive (stdin-port stdout-port stderr-port)
          (px.after-fork/prepare-child-binary-input/output-ports)
        (let ((buf (make-bytevector 5 0)))
          (get-bytevector-n! stdin-port buf 0 5)
          (assert (bytevector=? buf '#ve(ascii "ciao\n")))
          (put-bytevector stdout-port '#ve(ascii "out\n"))
          (put-bytevector stderr-port '#ve(ascii "err\n"))
          (flush-output-port stdout-port)
          (flush-output-port stderr-port)
          (exit 0)))))

  (flush-output-port (console-output-port))
  (flush-output-port (console-error-port))
  (px.fork parent-proc child-thunk))

here is the same example using fork-with-binary-ports:

(import (vicare)
  (prefix (vicare posix) px.))

(define (parent-proc child-pid
           child-stdin child-stdout child-stderr)
  (unwind-protect
      (let ((bufout (make-bytevector 4 0))
            (buferr (make-bytevector 4 0)))
        (put-bytevector child-stdin '#ve(ascii "ciao\n"))
        (flush-output-port child-stdin)
        (let ((status (px.waitpid child-pid 0)))
          (if (and (px.WIFEXITED status)
                   (zero? (px.WEXITSTATUS status)))
              (begin
                (get-bytevector-n! child-stdout bufout 0 4)
                (get-bytevector-n! child-stderr buferr 0 4)
                (values bufout buferr))
            (error #f
              "child process exited abnormally"
              status))))
    (close-output-port child-stdin)
    (close-input-port  child-stdout)
    (close-input-port  child-stderr)))

(define (child-thunk)
  (guard (E (else
             (print-condition E)
             (exit 1)))
    (define-constant stdin-port  (standard-input-port))
    (define-constant stdout-port (standard-output-port))
    (define-constant stderr-port (standard-error-port))
    (let ((buf (make-bytevector 5 0)))
      (get-bytevector-n! stdin-port buf 0 5)
      (assert (bytevector=? buf '#ve(ascii "ciao\n")))
      (put-bytevector stdout-port '#ve(ascii "out\n"))
      (put-bytevector stderr-port '#ve(ascii "err\n"))
      (flush-output-port stdout-port)
      (flush-output-port stderr-port)
      (exit 0))))

(px.fork-with-binary-ports parent-proc child-thunk)

Next: , Previous: , Up: posix process fork   [Index]