|
|
|
@ -32,7 +32,7 @@ packet, it is \emph{not} accessed through a global variable.
|
|
|
|
|
For reference purposes, the {\Unix} \ex{errno} numbers
|
|
|
|
|
are bound to the variables \ex{errno/perm}, \ex{errno/noent}, {\etc}
|
|
|
|
|
System calls never return \ex{error/intr}---they
|
|
|
|
|
automatically retry. (Currently only true for I/O calls.)
|
|
|
|
|
automatically retry.
|
|
|
|
|
|
|
|
|
|
\begin{dfndesc}
|
|
|
|
|
{errno-error}{errno syscall .\ data}{\noreturn}{procedure}
|
|
|
|
@ -111,10 +111,6 @@ the \ex{errno/intr} exception is never raised.
|
|
|
|
|
If the programmer wishes to abort a system call on an interrupt, he
|
|
|
|
|
should have the interrupt handler explicitly raise an exception or
|
|
|
|
|
invoke a stored continuation to throw out of the system call.
|
|
|
|
|
\remark{This is not strictly true in the current implementation---only
|
|
|
|
|
some of the i/o syscalls loop.
|
|
|
|
|
But BSD variants never return \ex{EINTR} anyway, unless you explicitly
|
|
|
|
|
request it, so we'll live w/it for now.}
|
|
|
|
|
\end{dfndescx}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -195,13 +191,13 @@ These procedures alter the dynamic binding of the current I/O port procedures
|
|
|
|
|
to new values.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\defun {close} {port/fd} {\boolean}
|
|
|
|
|
\defun {close} {fd/port} {\boolean}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
Close the port or file descriptor.
|
|
|
|
|
|
|
|
|
|
If \var{port/fd} is a file descriptor, and it has a port allocated to it,
|
|
|
|
|
If \var{fd/port} is a file descriptor, and it has a port allocated to it,
|
|
|
|
|
the port is shifted to a new file descriptor created with \ex{(dup
|
|
|
|
|
port/fd)} before closing \ex{port/fd}. The port then has its revealed
|
|
|
|
|
fd/port)} before closing \ex{fd/port}. The port then has its revealed
|
|
|
|
|
count set to zero. This reflects the design criteria that ports are not
|
|
|
|
|
associated with file descriptors, but with open files.
|
|
|
|
|
|
|
|
|
@ -238,9 +234,9 @@ to new values.
|
|
|
|
|
descriptors.
|
|
|
|
|
It is exactly equivalent to the series of assignments
|
|
|
|
|
\begin{code}
|
|
|
|
|
(set-current-input-port! (fdes->inport 0))
|
|
|
|
|
(set-current-output-port! (fdes->inport 1))
|
|
|
|
|
(set-error-output-port! (fdes->inport 2))\end{code}
|
|
|
|
|
(set-current-input-port! (fdes->inport 0))
|
|
|
|
|
(set-current-output-port! (fdes->outport 1))
|
|
|
|
|
(set-error-output-port! (fdes->outport 2))\end{code}
|
|
|
|
|
However, you are more likely to find the dynamic-extent variant,
|
|
|
|
|
\ex{with-stdio-ports*}, below, to be of use in general programming.
|
|
|
|
|
\end{desc}
|
|
|
|
@ -275,7 +271,7 @@ interface described herein may be liable to change.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\defun {make-string-output-port} {} {\port}
|
|
|
|
|
\defunx {string-output-port-output} {port} {\port}
|
|
|
|
|
\defunx {string-output-port-output} {port} {\str}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
A string output port is a port that collects the characters given to it into
|
|
|
|
|
a string.
|
|
|
|
@ -369,7 +365,7 @@ are used to shift back and forth between file descriptors and ports. When
|
|
|
|
|
\ex{port->fdes} reveals a port's file descriptor, it increments the port's
|
|
|
|
|
\var{revealed} field. When the user is through with the file descriptor, he
|
|
|
|
|
can call \ex{(release-port-handle \var{port})}, which decrements the count.
|
|
|
|
|
The function \ex{(call/fdes fdes/port \var{proc})} automates this protocol.
|
|
|
|
|
The function \ex{(call/fdes fd/port \var{proc})} automates this protocol.
|
|
|
|
|
\ex{call/fdes} uses \ex{dynamic-wind} to enforce the protocol.
|
|
|
|
|
If \var{proc} throws out of the \ex{call/fdes} application,
|
|
|
|
|
the unwind handler releases the descriptor handle;
|
|
|
|
@ -523,20 +519,20 @@ Decrement the port's revealed count.
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
\subsection{{\Unix} I/O}
|
|
|
|
|
|
|
|
|
|
\defun {dup} {port/fd [newfd]} {port/fd}
|
|
|
|
|
\defunx{dup->inport} {port/fd [newfd]} {port}
|
|
|
|
|
\defunx{dup->outport} {port/fd [newfd]} {port}
|
|
|
|
|
\defunx{dup->fdes} {port/fd [newfd]} {fd}
|
|
|
|
|
\defun {dup} {fd/port [newfd]} {fd/port}
|
|
|
|
|
\defunx{dup->inport} {fd/port [newfd]} {port}
|
|
|
|
|
\defunx{dup->outport} {fd/port [newfd]} {port}
|
|
|
|
|
\defunx{dup->fdes} {fd/port [newfd]} {fd}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
These procedures provide the functionality of C's \ex{dup()} and \ex{dup2()}.
|
|
|
|
|
The different routines return different types of values:
|
|
|
|
|
\ex{dup->inport}, \ex{dup->outport}, and \ex{dup->fdes} return
|
|
|
|
|
input ports, output ports, and integer file descriptors, respectively.
|
|
|
|
|
\ex{dup}'s return value depends on on the type of
|
|
|
|
|
\var{port/fd}---it maps fd$\rightarrow$fd and port$\rightarrow$port.
|
|
|
|
|
\var{fd/port}---it maps fd$\rightarrow$fd and port$\rightarrow$port.
|
|
|
|
|
|
|
|
|
|
These procedures use the {\Unix} \ex{dup()} syscall to replicate
|
|
|
|
|
the file descriptor or file port \var{port/fd}.
|
|
|
|
|
the file descriptor or file port \var{fd/port}.
|
|
|
|
|
If a \var{newfd} file descriptor is given, it is used as the target of
|
|
|
|
|
the dup operation, \ie, the operation is a \ex{dup2()}.
|
|
|
|
|
In this case, procedures that return a port (such as \ex{dup->inport})
|
|
|
|
@ -587,26 +583,17 @@ this is dependent on the OS implementation.
|
|
|
|
|
|
|
|
|
|
\begin{defundesc} {open-file} {fname flags [perms]} {\port}
|
|
|
|
|
\var{Perms} defaults to \cd{#o666}.
|
|
|
|
|
\var{Flags} is an integer bitmask, composed by or'ing together the following
|
|
|
|
|
constants:
|
|
|
|
|
\begin{code}\codeallowbreaks
|
|
|
|
|
open/read ; You may only
|
|
|
|
|
open/write ; choose one
|
|
|
|
|
open/read+write ; of these three
|
|
|
|
|
open/no-control-tty
|
|
|
|
|
open/nonblocking
|
|
|
|
|
open/append
|
|
|
|
|
open/create
|
|
|
|
|
open/truncate
|
|
|
|
|
open/exclusive
|
|
|
|
|
. ; Your Unix may have
|
|
|
|
|
. ; a few more.\end{code}
|
|
|
|
|
\var{Flags} is an integer bitmask, composed by or'ing together constants
|
|
|
|
|
listed in table~\ref{table:fdes-status-flags}
|
|
|
|
|
(page~\pageref{table:fdes-status-flags}).
|
|
|
|
|
You must use exactly one of the \ex{open/read}, \ex{open/write}, or
|
|
|
|
|
\ex{open/read+write} flags.
|
|
|
|
|
%
|
|
|
|
|
Returns a port. The port is an input port if the \var{flags} permit it,
|
|
|
|
|
otherwise an output port. \R4RS/\scm/scsh do not have input/output ports,
|
|
|
|
|
so it's one or the other. This should be fixed. (You can hack simultaneous
|
|
|
|
|
i/o on a file by opening it r/w, taking the result input port,
|
|
|
|
|
and duping it to an output port with \ex{dup->outport}.)
|
|
|
|
|
The returned port is an input port if the \var{flags} permit it,
|
|
|
|
|
otherwise an output port. \R4RS/\scm/scsh do not have input/output ports,
|
|
|
|
|
so it's one or the other. This should be fixed. (You can hack simultaneous
|
|
|
|
|
i/o on a file by opening it r/w, taking the result input port,
|
|
|
|
|
and duping it to an output port with \ex{dup->outport}.)
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\defun{open-input-file}{fname [flags]}\port
|
|
|
|
@ -626,6 +613,89 @@ and duping it to an output port with \ex{dup->outport}.)
|
|
|
|
|
Returns a file descriptor.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\defun{fdes-flags}{fd/port}{\integer}
|
|
|
|
|
\begin{defundescx}{set-fdes-flags}{fd/port \integer}{\undefined}
|
|
|
|
|
These procedures allow reading and writing of an open file's flags.
|
|
|
|
|
The only such flag defined by {\Posix} is \ex{fdflags/close-on-exec};
|
|
|
|
|
your {\Unix} implementation may provide others.
|
|
|
|
|
|
|
|
|
|
These procedures should not be particularly useful to the programmer,
|
|
|
|
|
as the scsh runtime already provides automatic control of the close-on-exec
|
|
|
|
|
property.
|
|
|
|
|
Unrevealed ports always have their file descriptors marked
|
|
|
|
|
close-on-exec, as they can be closed when the scsh process execs a new program.
|
|
|
|
|
Whenever the user reveals or unreveals a port's file descriptor,
|
|
|
|
|
the runtime automatically sets or clears the flag for the programmer.
|
|
|
|
|
Programmers that manipulate this flag should be aware of these extra, automatic
|
|
|
|
|
operations.
|
|
|
|
|
\end{defundescx}
|
|
|
|
|
|
|
|
|
|
\defun{fdes-status}{fd/port}{\integer}
|
|
|
|
|
\begin{defundescx}{set-fdes-status}{fd/port \integer}{\undefined}
|
|
|
|
|
These procedures allow reading and writing of an open file's status flags
|
|
|
|
|
(table~\ref{table:fdes-status-flags}).
|
|
|
|
|
%
|
|
|
|
|
\begin{table}
|
|
|
|
|
\begin{center}
|
|
|
|
|
\begin{tabular}{@{}rp{1.5in}>{\ttfamily}l@{}}
|
|
|
|
|
& Allowed operations & Status flag \\ \cline{2-3}
|
|
|
|
|
\textbf{Open+Get+Set} &
|
|
|
|
|
\parbox[t]{1.5in}{\raggedright
|
|
|
|
|
These flags can be used in \ex{open-file}, \ex{fdes-status},
|
|
|
|
|
and \ex{set-fdes-status} calls.} &
|
|
|
|
|
%
|
|
|
|
|
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
|
|
|
|
%% These are gettable and settable
|
|
|
|
|
open/append \\
|
|
|
|
|
open/non-blocking \\
|
|
|
|
|
open/async \textrm{(Non-\Posix)} \\
|
|
|
|
|
open/fsync \textrm{(Non-\Posix)}
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\\\cline{2-3}
|
|
|
|
|
\textbf{Open+Get} &
|
|
|
|
|
\parbox[t]{1.5in}{\raggedright
|
|
|
|
|
These flags can be used in \ex{open-file} and \ex{fdes-status} calls,
|
|
|
|
|
but are ignored by \ex{set-fdes-status}.\strut} &
|
|
|
|
|
%
|
|
|
|
|
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
|
|
|
|
%% These are gettable, not settable
|
|
|
|
|
open/read \\
|
|
|
|
|
open/write \\
|
|
|
|
|
open/read+write \\
|
|
|
|
|
open/access-mask
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\\\cline{2-3}
|
|
|
|
|
\textbf{Open} &
|
|
|
|
|
\parbox[t]{1.5in}{\raggedright
|
|
|
|
|
These flags are only relevant in
|
|
|
|
|
\ex{open-file} calls;
|
|
|
|
|
they are ignored by \ex{fdes-status} and \ex{set-fdes-status} calls.} &
|
|
|
|
|
%
|
|
|
|
|
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
|
|
|
|
%% These are neither gettable nor settable.
|
|
|
|
|
open/create \\
|
|
|
|
|
open/exclusive \\
|
|
|
|
|
open/no-control-tty \\
|
|
|
|
|
open/truncate
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\end{center}
|
|
|
|
|
\caption{Status flags for \texttt{open-file},
|
|
|
|
|
\texttt{fdes-status} and \texttt{set-fdes-status}.
|
|
|
|
|
Only {\Posix} flags are guaranteed to be present;
|
|
|
|
|
your operating system may define others.
|
|
|
|
|
The \texttt{open/access-mask} value is not an actual flag,
|
|
|
|
|
but a bit mask used to select the field for the \texttt{open/read},
|
|
|
|
|
\texttt{open/write} and \texttt{open/read+write} bits.
|
|
|
|
|
}
|
|
|
|
|
\label{table:fdes-status-flags}
|
|
|
|
|
\end{table}
|
|
|
|
|
|
|
|
|
|
Note that this file-descriptor state is shared between file descriptors
|
|
|
|
|
created by \ex{dup}---if you create port \var{b} by applying \ex{dup}
|
|
|
|
|
to port \var{a}, and change {\var{b}}'s status flags, you will also have
|
|
|
|
|
changed {\var{a}}'s status flags.
|
|
|
|
|
\end{defundescx}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{pipe}{} {[\var{rport} \var{wport}]}
|
|
|
|
|
Returns two ports, the read and write end-points of a {\Unix} pipe.
|
|
|
|
@ -702,8 +772,8 @@ Returns two ports, the read and write end-points of a {\Unix} pipe.
|
|
|
|
|
of any particular read operation.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\defun {select }{rvec wvec evec [timeout]}{rvec' wvec' evec'}
|
|
|
|
|
\defunx{select!}{rvec wvec evec [timeout]}{nr nw ne}
|
|
|
|
|
\defun {select }{rvec wvec evec [timeout]}{[rvec' wvec' evec']}
|
|
|
|
|
\defunx{select!}{rvec wvec evec [timeout]}{[nr nw ne]}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
The \ex{select} procedure allows a process to block and wait for events on
|
|
|
|
|
multiple I/O channels.
|
|
|
|
@ -849,14 +919,14 @@ buffering is turned off
|
|
|
|
|
$\var{policy} = \ex{bufpol/none}$).
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{force-output} {[fd/port]}{\noreturn}
|
|
|
|
|
\begin{defundesc}{force-output} {[fd/port]}{\undefined}
|
|
|
|
|
This procedure does nothing when applied to an integer file descriptor
|
|
|
|
|
or unbuffered port.
|
|
|
|
|
It flushes buffered output when applied to a buffered port,
|
|
|
|
|
and raises a write-error exception on error. Returns no value.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{flush-all-ports} {}{\noreturn}
|
|
|
|
|
\begin{defundesc}{flush-all-ports} {}{\undefined}
|
|
|
|
|
This procedure flushes all open output ports with buffered data.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
@ -877,6 +947,11 @@ not with associated open file descriptors.
|
|
|
|
|
Once a process locks a file, using some file descriptor \var{fd},
|
|
|
|
|
the next time \emph{any} file descriptor referencing that file is closed,
|
|
|
|
|
all associated locks are released.
|
|
|
|
|
This severely limits the utility of {\Posix} advisory file locks,
|
|
|
|
|
and we'd recommend caution when using them.
|
|
|
|
|
It is not without reason that the FreeBSD man pages refer to {\Posix}
|
|
|
|
|
file locking as ``completely stupid.''
|
|
|
|
|
|
|
|
|
|
Scsh moves Scheme ports from file descriptor to file descriptor with
|
|
|
|
|
\ex{dup()} and \ex{close()} as required by the runtime,
|
|
|
|
|
so it is impossible to keep file locks open across one of these shifts.
|
|
|
|
@ -892,6 +967,7 @@ associated file descriptor.
|
|
|
|
|
NeXTSTEP users should also note that even minimalist {\Posix} file locking
|
|
|
|
|
is not supported for NFS-mounted files in NeXTSTEP; NeXT claims they will
|
|
|
|
|
fix this in NS release 4.
|
|
|
|
|
We'd appreciate hearing from users when and if this happens.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{\Posix} allows the user to lock a region of a file with either
|
|
|
|
@ -903,14 +979,18 @@ Locked regions are described by the \emph{lock-region} record:
|
|
|
|
|
start
|
|
|
|
|
len
|
|
|
|
|
whence
|
|
|
|
|
pid)\end{code}
|
|
|
|
|
\index{lock-region?}
|
|
|
|
|
\index{lock-region:exclusive?} \index{lock-region:whence}
|
|
|
|
|
\index{lock-region:start} \index{lock-region:end}
|
|
|
|
|
\index{lock-region:len} \index{lock-region:pid}
|
|
|
|
|
proc)\end{code}%
|
|
|
|
|
\index{lock-region?}%
|
|
|
|
|
\index{lock-region:exclusive?} \index{lock-region:whence}%
|
|
|
|
|
\index{lock-region:start} \index{lock-region:end}%
|
|
|
|
|
\index{lock-region:len} \index{lock-region:proc}%
|
|
|
|
|
%
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item
|
|
|
|
|
The \ex{exclusive?} field is true if the lock is exclusive;
|
|
|
|
|
false if it is shared.
|
|
|
|
|
|
|
|
|
|
\item
|
|
|
|
|
The \ex{whence} field is one of the values from the \ex{seek} call:
|
|
|
|
|
\ex{seek/set}, \ex{seek/delta}, or \ex{seek/end},
|
|
|
|
|
and determines the interpretation of the \ex{start} field:
|
|
|
|
@ -923,9 +1003,15 @@ file descriptor's current position in the file.
|
|
|
|
|
end of the file.
|
|
|
|
|
\end{itemize}
|
|
|
|
|
The region of the file being locked is given by the \ex{start} and \ex{len}
|
|
|
|
|
fields.
|
|
|
|
|
The \ex{pid} field gives the process id of the process holding the region
|
|
|
|
|
fields;
|
|
|
|
|
if \ex{len} is zero, it means ``infinity,'' that is, the region extends
|
|
|
|
|
from the starting point through the end of the file, even as the file is
|
|
|
|
|
extended by subsequent write operations.
|
|
|
|
|
|
|
|
|
|
\item
|
|
|
|
|
The \ex{proc} field gives the process object for the process holding the region
|
|
|
|
|
lock, when relevant (see \ex{get-lock-region} below).
|
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{make-lock-region}{exclusive? start len [whence]}{lock-region}
|
|
|
|
|
This procedure makes a lock-region record.
|
|
|
|
@ -940,14 +1026,24 @@ These procedures lock a region of the file referenced by file descriptor
|
|
|
|
|
The \ex{lock-region} procedure blocks until the lock is granted;
|
|
|
|
|
the non-blocking variant returns a boolean indicating whether or not
|
|
|
|
|
the lock was granted.
|
|
|
|
|
To take an exclusive (write) lock, you must have the file descriptor
|
|
|
|
|
open with write access;
|
|
|
|
|
to take a shared (read) lock, you must have the file descriptor
|
|
|
|
|
open with read access.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{get-lock-region}{fdes lock}{lock-region or \sharpf}
|
|
|
|
|
Return the first lock region on \var{fdes} that overlaps with
|
|
|
|
|
the lock region \var{lock}.
|
|
|
|
|
If there is no such lock, return false.
|
|
|
|
|
This procedure fills out the \ex{pid} field of the returned lock region,
|
|
|
|
|
Return the first lock region on \var{fdes} that would conflict with
|
|
|
|
|
lock region \var{lock}.
|
|
|
|
|
If there is no such lock region, return false.
|
|
|
|
|
This procedure fills out the \ex{proc} field of the returned lock region,
|
|
|
|
|
and is the only procedure that has anything to do with this field.
|
|
|
|
|
(See section~\ref{sec:proc-objects} for a description of process objects.)
|
|
|
|
|
Note that if you apply this procedure to a file system that is shared
|
|
|
|
|
across multiple operating systems (\ie, an NFS file system), the \ex{proc}
|
|
|
|
|
field may be ambiguous.
|
|
|
|
|
We note, again, that {\Posix} advisory file locking is not a terribly useful
|
|
|
|
|
or well-designed facility.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{unlock-region}{fdes lock}{\undefined}
|
|
|
|
@ -1705,7 +1801,7 @@ Suspend the current process with a SIGSTOP signal.
|
|
|
|
|
\begin{code}
|
|
|
|
|
(fork (\l{} (fork/pipe a) (b)))\end{code}
|
|
|
|
|
%
|
|
|
|
|
which returns the pid of \ex{b}'s process.
|
|
|
|
|
which returns the process object for \ex{b}'s process.
|
|
|
|
|
|
|
|
|
|
To create a background three-process pipe \ex{a | b | c}, we write:
|
|
|
|
|
%
|
|
|
|
@ -1714,7 +1810,7 @@ Suspend the current process with a SIGSTOP signal.
|
|
|
|
|
(fork/pipe b)
|
|
|
|
|
(c)))\end{code}
|
|
|
|
|
%
|
|
|
|
|
which returns the pid of \ex{c}'s process.
|
|
|
|
|
which returns the process object for \ex{c}'s process.
|
|
|
|
|
|
|
|
|
|
Note that these procedures affect file descriptors, not ports.
|
|
|
|
|
That is, the pipe is allocated connecting the child's file descriptor
|
|
|
|
@ -1844,18 +1940,22 @@ values \ex{'early}, \ex{'late}, or {\sharpf} (\ie, no autoreap).
|
|
|
|
|
\begin{description}
|
|
|
|
|
\item [early]
|
|
|
|
|
The child is reaped from the {\Unix} kernel's process table
|
|
|
|
|
into scsh as soon as possible after it dies. In the current
|
|
|
|
|
release of scsh, this happens at the next call to
|
|
|
|
|
\ex{wait}---when scsh is asked to wait for a particular
|
|
|
|
|
child to exit, it will reap \emph{all} outstanding zombies.
|
|
|
|
|
When signal handlers are added to a future release of scsh,
|
|
|
|
|
early autoreaping will use the \ex{SIGCHLD} signal to reap
|
|
|
|
|
zombies with minimum delay.
|
|
|
|
|
into scsh as soon as it dies. This is done by having a
|
|
|
|
|
signal handler for the \ex{SIGCHLD} signal reap the process.
|
|
|
|
|
\emph{
|
|
|
|
|
If a scsh program sets its own handler for the \ex{SIGCHLD}
|
|
|
|
|
signal, the handler must reap dead children
|
|
|
|
|
by calling \ex{wait}, \ex{wait-any}, or \ex{reap-zombies}.}
|
|
|
|
|
We deprecate interrupt-driven code, and hope to provide
|
|
|
|
|
alternative tools in a future, multi-threaded release of scsh.
|
|
|
|
|
|
|
|
|
|
\item [late]
|
|
|
|
|
The child is not autoreaped until it dies \emph{and} the scsh program
|
|
|
|
|
drops all pointers to its process object. That is, the process
|
|
|
|
|
table is cleaned out during garbage collection.
|
|
|
|
|
\oops{The \ex{late} policy is not supported under the current
|
|
|
|
|
release of scsh. It requires more sophisticated gc hooks than
|
|
|
|
|
we can get from the release of {\scm} that we use.}
|
|
|
|
|
|
|
|
|
|
\item [\sharpf]
|
|
|
|
|
If autoreaping is turned off, process reaping is completely under
|
|
|
|
@ -2043,8 +2143,8 @@ Otherwise, this function returns false.
|
|
|
|
|
|
|
|
|
|
\defun {umask}{} \fixnum
|
|
|
|
|
\defunx {set-umask} {perms} \undefined
|
|
|
|
|
\defunx {with-umask*} {perms thunk} {values of thunk}
|
|
|
|
|
\dfnx {with-umask} {perms . body} {values of body} {syntax}
|
|
|
|
|
\defunx {with-umask*} {perms thunk} {value(s) of thunk}
|
|
|
|
|
\dfnx {with-umask} {perms . body} {value(s) of body} {syntax}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
The process' current umask is retrieved with \ex{umask}, and set with
|
|
|
|
|
\ex{(set-umask \var{perms})}. Calling \ex{with-umask*} changes the umask
|
|
|
|
@ -2080,20 +2180,20 @@ The special form \ex{with-cwd} is simply syntactic sugar for \ex{with-cwd*}.
|
|
|
|
|
\defun {pid}{} \fixnum
|
|
|
|
|
\defunx {parent-pid}{} \fixnum
|
|
|
|
|
\defunx {process-group} {} \fixnum
|
|
|
|
|
\defunx {set-process-group} {[proc] pgrp} \undefined % [not implemented]
|
|
|
|
|
\defunx {set-process-group} {[proc/pid] pgrp} \undefined % [not implemented]
|
|
|
|
|
\begin{desc}
|
|
|
|
|
\ex{(pid)} and \ex{(parent-pid)} retrieve the process id for the
|
|
|
|
|
current process and its parent.
|
|
|
|
|
\ex{(process-group)} returns the process group of the current process.
|
|
|
|
|
A process' process-group can be set with \ex{set-process-group};
|
|
|
|
|
the value \var{pid} specifies the affected process. It may be either
|
|
|
|
|
the value \var{proc/pid} specifies the affected process. It may be either
|
|
|
|
|
a process object or an integer process id, and defaults to the current
|
|
|
|
|
process.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\defun {set-priority} {which who priority} \undefined %; priority stuff unimplemented
|
|
|
|
|
\defunx {priority} {which who} \fixnum % ; not implemented
|
|
|
|
|
\defunx {nice} {[pid delta]} \undefined %; not implemented
|
|
|
|
|
\defunx {nice} {[proc/pid delta]} \undefined %; not implemented
|
|
|
|
|
\begin{desc}
|
|
|
|
|
These procedures set and access the priority of processes.
|
|
|
|
|
I can't remember how \ex{set-priority} and \ex{priority} work, so no
|
|
|
|
@ -2279,7 +2379,8 @@ fully-qualified domain name such as ``solar.csie.ntu.edu.tw.''
|
|
|
|
|
\section{Signal system}
|
|
|
|
|
|
|
|
|
|
Signal numbers are bound to the variables \ex{signal/hup}, \ex{signal/int},
|
|
|
|
|
\ldots
|
|
|
|
|
\ldots. See tables~\ref{table:signals-and-interrupts} and
|
|
|
|
|
\ref{table:uncatchable-signals} for the full list.
|
|
|
|
|
|
|
|
|
|
\defun {signal-process} {proc sig} \undefined
|
|
|
|
|
\defunx {signal-process-group} {prgrp sig} \undefined
|
|
|
|
@ -2290,24 +2391,194 @@ The \var{proc} and \var{prgrp} arguments are either processes
|
|
|
|
|
or integer process ids.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
I haven't done signal handlers yet. Should be straightforward: a mechanism
|
|
|
|
|
to assign procedures to signals.
|
|
|
|
|
|
|
|
|
|
\defun{itimer}{???} \undefined
|
|
|
|
|
\defunx{pause-until-interrupt}{} \undefined
|
|
|
|
|
|
|
|
|
|
\defun{sleep}{secs} \undefined
|
|
|
|
|
\defunx{sleep-until}{time}\undefined
|
|
|
|
|
\begin{desc}
|
|
|
|
|
Sleeping is defined, but we don't offer a way to sleep for a more precise
|
|
|
|
|
interval (\eg, a microsecond timer), as this is not in {\Posix}.
|
|
|
|
|
The \ex{sleep} procedure causes the process to sleep for \var{secs} seconds.
|
|
|
|
|
The \ex{sleep-until} procedure causes the process to sleep until \var{time}
|
|
|
|
|
(see section~\ref{sec:time}).
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\subsubsection{Interrupt handlers}
|
|
|
|
|
Scsh interrupt handlers are complicated by the fact that scsh is implemented on
|
|
|
|
|
top of the {\scm} virtual machine, which has its own interrupt system,
|
|
|
|
|
independent of the Unix signal system.
|
|
|
|
|
This means that {\Unix} signals are delivered in two stages: first,
|
|
|
|
|
{\Unix} delivers the signal to the {\scm} virtual machine, then
|
|
|
|
|
the {\scm} virtual machine delivers the signal to the executing Scheme program
|
|
|
|
|
as a {\scm} interrupt.
|
|
|
|
|
This ensures that signal delivery happens between two vm instructions,
|
|
|
|
|
keeping individual instructions atomic.
|
|
|
|
|
|
|
|
|
|
The {\scm} machine has its own set of interrupts, which includes the
|
|
|
|
|
asynchronous {\Unix} signals (table~\ref{table:signals-and-interrupts}).
|
|
|
|
|
\begin{table}
|
|
|
|
|
\begin{minipage}{\textwidth}
|
|
|
|
|
\begin{center}
|
|
|
|
|
\newcommand{\kwd}[1]{\index{\texttt{#1}}\texttt{#1}}
|
|
|
|
|
\begin{tabular}{lll}\hline
|
|
|
|
|
Interrupt & Unix signal & OS Variant \\ \hline\hline
|
|
|
|
|
\kwd{interrupt/alrm}\footnote{Also bound to {\scm} interrupt
|
|
|
|
|
\kwd{interrupt/alarm}.}
|
|
|
|
|
& \kwd{signal/alrm} & \Posix \\
|
|
|
|
|
%
|
|
|
|
|
\kwd{interrupt/int}\footnote{Also bound to {\scm} interrupt
|
|
|
|
|
\kwd{interrupt/keyboard}.}
|
|
|
|
|
& \kwd{signal/int} & \Posix \\
|
|
|
|
|
%
|
|
|
|
|
\kwd{interrupt/memory-shortage} & N/A & \\
|
|
|
|
|
\kwd{interrupt/chld} & \kwd{signal/chld} & \Posix \\
|
|
|
|
|
\kwd{interrupt/cont} & \kwd{signal/cont} & \Posix \\
|
|
|
|
|
\kwd{interrupt/hup} & \kwd{signal/hup} & \Posix \\
|
|
|
|
|
\kwd{interrupt/quit} & \kwd{signal/quit} & \Posix \\
|
|
|
|
|
\kwd{interrupt/term} & \kwd{signal/term} & \Posix \\
|
|
|
|
|
\kwd{interrupt/tstp} & \kwd{signal/tstp} & \Posix \\
|
|
|
|
|
\kwd{interrupt/usr1} & \kwd{signal/usr1} & \Posix \\
|
|
|
|
|
\kwd{interrupt/usr2} & \kwd{signal/usr2} & \Posix \\
|
|
|
|
|
\\
|
|
|
|
|
\kwd{interrupt/info} & \kwd{signal/info} & BSD only \\
|
|
|
|
|
\kwd{interrupt/io} & \kwd{signal/io} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/poll} & \kwd{signal/poll} & SVR4 only \\
|
|
|
|
|
\kwd{interrupt/prof} & \kwd{signal/prof} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/pwr} & \kwd{signal/pwr} & SVR4 only \\
|
|
|
|
|
\kwd{interrupt/urg} & \kwd{signal/urg} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/vtalrm} & \kwd{signal/vtalrm} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/winch} & \kwd{signal/winch} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/xcpu} & \kwd{signal/xcpu} & BSD + SVR4 \\
|
|
|
|
|
\kwd{interrupt/xfsz} & \kwd{signal/xfsz} & BSD + SVR4 \\
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\end{center}
|
|
|
|
|
\caption{{\scm} virtual-machine interrupts and related {\Unix} signals.
|
|
|
|
|
Only the {\Posix} signals are guaranteed to be defined; however,
|
|
|
|
|
your implementation and OS may define other signals and
|
|
|
|
|
interrupts not listed here.}
|
|
|
|
|
\end{minipage}
|
|
|
|
|
\label{table:signals-and-interrupts}
|
|
|
|
|
\end{table}
|
|
|
|
|
%
|
|
|
|
|
\begin{table}
|
|
|
|
|
\newcommand{\kwd}[1]{\index{\texttt{#1}}\texttt{#1}}
|
|
|
|
|
\begin{center}
|
|
|
|
|
\begin{tabular}{lll}\hline
|
|
|
|
|
Unix signal & Type & OS Variant \\ \hline\hline
|
|
|
|
|
\kwd{signal/stop} & Uncatchable & \Posix \\
|
|
|
|
|
\kwd{signal/kill} & Uncatchable & \Posix \\
|
|
|
|
|
\\
|
|
|
|
|
\kwd{signal/abrt} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/fpe} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/ill} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/pipe} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/segv} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/ttin} & Synchronous & \Posix \\
|
|
|
|
|
\kwd{signal/ttou} & Synchronous & \Posix \\
|
|
|
|
|
\\
|
|
|
|
|
\kwd{signal/bus} & Synchronous & BSD + SVR4 \\
|
|
|
|
|
\kwd{signal/emt} & Synchronous & BSD + SVR4 \\
|
|
|
|
|
\kwd{signal/iot} & Synchronous & BSD + SVR4 \\
|
|
|
|
|
\kwd{signal/sys} & Synchronous & BSD + SVR4 \\
|
|
|
|
|
\kwd{signal/trap} & Synchronous & BSD + SVR4 \\
|
|
|
|
|
\end{tabular}
|
|
|
|
|
\end{center}
|
|
|
|
|
\caption{Uncatchable and synchronous {\Unix} signals. While these signals
|
|
|
|
|
may be sent with \texttt{signal-process} or
|
|
|
|
|
\texttt{signal-process-group},
|
|
|
|
|
there are no corresponding scsh interrupt handlers.
|
|
|
|
|
Only the {\Posix} signals are guaranteed to be defined; however,
|
|
|
|
|
your implementation and OS may define other signals not listed
|
|
|
|
|
here.}
|
|
|
|
|
\label{table:uncatchable-signals}
|
|
|
|
|
\end{table}
|
|
|
|
|
Note that scsh does \emph{not} support signal handlers for ``synchronous''
|
|
|
|
|
{\Unix} signals, such as \ex{signal/ill} or \ex{signal/pipe}
|
|
|
|
|
(see table~\ref{table:uncatchable-signals}).
|
|
|
|
|
Synchronous occurrences of these signals are better handled by raising
|
|
|
|
|
a Scheme exception.
|
|
|
|
|
We recommend you avoid using signal handlers unless you absolutely have
|
|
|
|
|
to; we intend to provide a better, higher-level interface to {\Unix}
|
|
|
|
|
signals after scsh has been ported to a multi-threaded platform.
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{signal->interrupt}{\integer}{\integer}
|
|
|
|
|
The programmer maps from {\Unix} signals to {\scm} interrupts with the
|
|
|
|
|
\ex{signal->interrupt} procedure.
|
|
|
|
|
If the signal does not have a defined {\scm} interrupt, an errror is signaled.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{interrupt-set}{\zeroormore{\integer}}{\integer}
|
|
|
|
|
This procedure builds interrupt sets from its interrupt arguments.
|
|
|
|
|
A set is represented as an integer using a two's-complement representation of
|
|
|
|
|
the bit set.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\defun{enabled-interrupts}{}{interrupt-set}
|
|
|
|
|
\defunx{set-enabled-interrupts}{interrupt-set}{interrupt-set}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
Get and set the value of the enabled-interrupt set.
|
|
|
|
|
Only interrupts in this set have their handlers called when delivered.
|
|
|
|
|
When a disabled interrupt is delivered to the {\scm} machine, it is
|
|
|
|
|
held pending until it becomes enabled, at which time its handler is invoked.
|
|
|
|
|
|
|
|
|
|
Interrupt sets are represented as integer bit sets (constructed with
|
|
|
|
|
the \ex{interrupt-set} function).
|
|
|
|
|
The \ex{set-enabled-interrupts} procedure returns the previous value of
|
|
|
|
|
the enabled-interrupt set.
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
\dfn {with-enabled-interrupts} {interrupt-set . body} {value(s) of body} {syntax}
|
|
|
|
|
\defunx{with-enabled-interrupts*}{interrupt-set thunk} {value(s) of thunk}
|
|
|
|
|
\begin{desc}
|
|
|
|
|
Run code with a given set of interrupts enabled.
|
|
|
|
|
Note that ``enabling'' an interrupt means enabling delivery from
|
|
|
|
|
the {\scm} vm to the scsh program.
|
|
|
|
|
Using the {\scm} interrupt system is fairly lightweight, and does not involve
|
|
|
|
|
actually making a system call.
|
|
|
|
|
Note that enabling an interrupt means that the assigned interrupt handler
|
|
|
|
|
is allowed to run when the interrupt is delivered.
|
|
|
|
|
Interrupts not enabled are held pending when delivered.
|
|
|
|
|
|
|
|
|
|
Interrupt sets are represented as integer bit sets (constructed with
|
|
|
|
|
the \ex{interrupt-set} function).
|
|
|
|
|
\end{desc}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{set-interrupt-handler}{interrupt handler}{old-handler}
|
|
|
|
|
Assigns a handler for a given interrupt,
|
|
|
|
|
and returns the interrupt's old handler.
|
|
|
|
|
The \var{handler} argument is \ex{\#f} (ignore), \ex{\#t} (default), or a
|
|
|
|
|
procedure taking an integer argument;
|
|
|
|
|
the return value follows the same conventions.
|
|
|
|
|
Note that the \var{interrupt} argument is an interrupt value,
|
|
|
|
|
not a signal value.
|
|
|
|
|
An interrupt is delivered to the {\scm} machine by (1) blocking all interrupts,
|
|
|
|
|
and (2) applying the handler procedure to the set of interrupts
|
|
|
|
|
that were enabled prior to the interrupt delivery.
|
|
|
|
|
If the procedure returns normally (\ie, it doesn't throw to a continuation),
|
|
|
|
|
the set of enabled interrupts will be returned to its previous value.
|
|
|
|
|
(To restore the enabled-interrupt set before throwing out of an interrupt
|
|
|
|
|
handler, see \ex{set-enabled-interrupts})
|
|
|
|
|
|
|
|
|
|
\note{If you set a handler for the \ex{interrupt/chld} interrupt,
|
|
|
|
|
you may break scsh's autoreaping process machinery. See the
|
|
|
|
|
discussion of autoreaping in section~\ref{sec:proc-objects}.}
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
\begin{defundesc}{interrupt-handler}{interrupt}{handler}
|
|
|
|
|
Return the handler for a given interrupt.
|
|
|
|
|
Note that the argument is an interrupt value, not a signal value.
|
|
|
|
|
A handler is either \ex{\#f} (ignore), \ex{\#t} (default), or a
|
|
|
|
|
procedure taking an integer argument.
|
|
|
|
|
\end{defundesc}
|
|
|
|
|
|
|
|
|
|
% %set-unix-signal-handler
|
|
|
|
|
% %unix-signal-handler
|
|
|
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
\section{Time}
|
|
|
|
|
\label{sec:time}
|
|
|
|
|
This time package does not currently work with NeXTSTEP, as NeXTSTEP
|
|
|
|
|
does not provide a {\Posix}-compliant time library that will even link.
|
|
|
|
|
|
|
|
|
|
Scsh's time system is fairly sophisticated, particularly with respect
|
|
|
|
|
to its careful treatment of time zones.
|
|
|
|
@ -2316,6 +2587,9 @@ all of the complexity is optional,
|
|
|
|
|
and defaulting all the optional arguments reduces the system
|
|
|
|
|
to a simple interface.
|
|
|
|
|
|
|
|
|
|
\remark{This time package does not currently work with NeXTSTEP, as NeXTSTEP
|
|
|
|
|
does not provide a {\Posix}-compliant time library that will even link.}
|
|
|
|
|
|
|
|
|
|
\subsection{Terminology}
|
|
|
|
|
``UTC'' and ``UCT'' stand for ``universal coordinated time,'' which is the
|
|
|
|
|
official name for what is colloquially referred to as ``Greenwich Mean
|
|
|
|
|