Previous: , Up: posix process fork   [Index]


4.6.2.4 Preparing textual input/output ports

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

Wrapper for fork that sets up the file descriptor pipes and textual 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 textual output port writing into the standard input of the child process.

parent<-child-stdout

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

parent<-child-stderr

It is a textual 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 console-input-port, console-output-port, console-error-port which are made to wrap standard file descriptors distinct from the parent’s standard file descriptors.

Function: after-fork/prepare-child-textual-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 textual input and output ports wrapping the standard file descriptors. New textual input and output ports are built and selected as values returned by console-input-port, console-output-port and console-error-port, we must use these functions to access the new ports. Return unspecified values.

It is responsibility of the caller to set the new ports as top values for the parameters current-input-port, current-output-port, current-error-port.

Function: after-fork/prepare-parent-textual-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 textual 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. Textual output port that writes in the standard input of the child process. Closing this port will also close the underlying file descriptor.
  2. Textual input port that reads from the standard output of the child process. Closing this port will also close the underlying file descriptor.
  3. Textual 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 textual ports in both the parent and child, waits for the 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-textual-input/output-ports
             parent->child-stdin
             parent<-child-stdout
             parent<-child-stderr)
      (unwind-protect
          (let ((bufout (make-string 4 #\x00))
                (buferr (make-string 4 #\x00)))
            (put-string child-stdin "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-string-n! child-stdout bufout 0 4)
                    (get-string-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)
      (px.after-fork/prepare-child-textual-input/output-ports)
      (let ((buf (make-string 5 #\x00)))
        (get-string-n! (console-input-port) buf 0 5)
        (assert (string=? buf "ciao\n"))
        (put-string (console-output-port) "out\n")
        (put-string (console-error-port) "err\n")
        (flush-output-port (console-output-port))
        (flush-output-port (console-error-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-textual-ports:

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

(define (parent-proc child-pid
           child-stdin child-stdout child-stderr)
  (unwind-protect
      (let ((bufout (make-string 4 #\x00))
            (buferr (make-string 4 #\x00)))
        (put-string child-stdin "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-string-n! child-stdout bufout 0 4)
                (get-string-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)))
    (let ((buf (make-string 5 #\x00)))
      (get-string-n! (console-input-port) buf 0 5)
      (assert (string=? buf "ciao\n"))
      (put-string (console-output-port) "out\n")
      (put-string (console-error-port) "err\n")
      (flush-output-port (console-output-port))
      (flush-output-port (console-error-port))
      (exit 0))))

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

Previous: , Up: posix process fork   [Index]