Previous: posix fd device blocking, Up: posix fd device [Index]
On POSIX platforms, right after a fork
call: the parent and child will
share all the input/output file descriptors that are open at the time of the
fork
call. This is problematic.
Let’s see what happens with the following program in which we open a file, fork the process then close the file in both the parent and child:
#!vicare (import (vicare) (prefix (vicare posix) px.)) (define (parent-proc child-pid) (px.waitpid child-pid 0) (close-output-port port) (exit 0)) (define (child-thunk) (close-output-port port) (exit 0)) (define port (parametrise ((output-file-buffer-size 8)) (open-file-output-port "demo.txt" (file-options no-fail) (buffer-mode block) (native-transcoder)))) (put-string port "0123456789ABCDEF") (px.fork parent-proc child-thunk)
the output port has a buffer of 8
characters and the string written to
it is 16
characters long; the call to put-string
immediately flushes
the first 8
characters and leaves the rest in the output buffer. The
fork
call causes the output buffer and its contents to be duplicated, so, when
we close the port, the two buffers are flushed to the same file. The resulting file
contents are:
0123456789ABCDEF89ABCDEF
which is not what we want.
POSIX has a partial solution for this problem: to configure file descriptors as close–on–exec; Vicare extends this to propose a partial solution: to configure ports as close–on–exec. Notice that it is close–on–exec, not close–on–fork. So we can try to address this problem by:
fork
: flush the ports in close–on–exec mode.
Here is the example above modified to do so:
#!vicare (import (vicare) (prefix (vicare posix) px.)) (define (parent-proc child-pid) (px.waitpid child-pid 0) (close-output-port port) (exit 0)) (define (child-thunk) (px.close-ports-in-close-on-exec-mode) (exit 0)) (define port (parametrise ((output-file-buffer-size 8)) (open-file-output-port "demo.txt" (file-options no-fail) (buffer-mode block) (native-transcoder)))) (px.port-set-close-on-exec-mode! port) (put-string port "0123456789ABCDEF") (px.flush-ports-in-close-on-exec-mode) (px.fork parent-proc child-thunk)
Special interface to the C function fcntl()
, (libc)fcntl. Configure the file descriptor fd in “close
on exec” mode or “do not close on exec” mode; if successful return
unspecified values, else raise an exception.
Special interface to the C function fcntl()
, (libc)fcntl. Query the file descriptor fd for its “close
on exec” mode; if successful: return #t
if fd is in “close
on exec” mode, #f
otherwise. If an error occurs: raise an
exception.
Register a Scheme port to be closed if the current process uses
one of the exec
functions. If successful: return unspecified
values, else raise an exception.
port can be any port: it is not required for it to have a file descriptor as underlying device. If the underlying device is a file descriptor: this descriptor is configured in close–on–exec mode.
Unregister a Scheme port so that it is not closed if the
current process uses one of the exec
functions. If successful:
return unspecified values, else raise an exception.
If the underlying device is a file descriptor: this descriptor is configured not to be in close–on–exec mode.
Return a boolean: true if port is in close–on–exec mode, false otherwise.
Close all the ports registered to be in close–on–exec mode. Each port
is closed by applying close-port
to it.
close-port
raises an exception,
the exception is blocked and discarded.
close-port
to the
port; if error-handler raises an exception, the exception is
blocked and discarded.
Flush the output buffer of all the output ports registered to be in
close–on–exec mode. Each port is processed by applying
flush-output-port
to it.
flush-output-port
raises an
exception, the exception is blocked and discarded.
flush-output-port
to
the port; if error-handler raises an exception, the exception is
blocked and discarded.
Previous: posix fd device blocking, Up: posix fd device [Index]