For Development HEAD DRAFTSearch (procedure/syntax/module):

6.24 System interface

Gauche supports most of POSIX.1 functions and other system functions popular among Unix variants as built-in procedures.

Lots of Scheme implementations provide some sort of system interface under various APIs. Some are just called by different names (e.g, delete-file or remove-file or unlink to delete a file), some do more abstraction introducing new Scheme objects. Instead of just picking one of such interfaces, I decided to implement Gauche’s system interface API in two layers; the lower level layer, described in this section, follows the operating system’s API as close as possible. On top of that, the higher-level APIs are provided, with considering compatibility to the existing systems.

The low level system interface has the name sys-name and usually correspond to the system call name. I tried to keep the interface similar whenever reasonable.

Gauche restarts a system call after it is interrupted by a signal by default. See Signal for the details.

If you are familiar with system programming in C, see also C to Scheme mapping, which shows correspondence between C standard library functions and Gauche procedures.


6.24.1 Program termination

Gauche has a few ways to terminate itself (other than returning from main). The exit procedure is a graceful way with all proper cleanups. sys-exit and sys-abort may be used in emergency where proper cleanup is impossible.

Function: exit :optional (code 0) (fmtstr #f) args …

[R7RS+ process-context] Terminates the current process with the exit code code. The optional code argument specifies the exit status; #t indicates a success (exit code 0), #f indicates a failure (exit code 1), and an exact integer specifies other exit code (only the lower 8 bits are used). Any other values of code makes the exit code to be 70 (EX_SOFTWARE. Note that R7RS does not specify how code is translated to OS’s exit status, except that #t indicates a success and #f indicates a failure. Portable code should only pass #t or #f.

When a string is given to fmtstr, it is passed to format (see Output), with the rest arguments args, to produce a message to the standard error port (not the current error port; see Common port operations).

In fact, the exiting procedure is a bit more complicated. The precise steps of exiting is as follow.

  1. The value of parameter exit-handler is checked. If it is not #f, the value is called as a procedure with three arguments: code, fmtstr, and a list of rest arguments. It is the default procedure of exit-handler that prints out the message to the standard error port. If an error occurs within exit handler, it is captured and discarded. Other exceptions are not caught.
  2. The after thunks of the active dynamic winds are invoked. Any exceptions raised in after thunks are captured and discarded.
  3. The clean-up handlers registered via C API Scm_AddCleanupHandler are invoked. These are usually responsible for under-the-hood cleanup jobs for each application that embeds Gauche. From the Scheme world there’s not much to care.
  4. The unclosed output buffered ports are flushed.
  5. The process exits with an integer derived from code as an exit code, via exit(3).

The exit-handler mechanism allows the application to hook its exit operation. Note that it is not for simple cleanup jobs; dynamic-wind, guard or unwind-protect are more appropriate. exit-handler is for more specific use just upon application exit. For example, GUI applications may want to post a dialog instead of printing to stderr.

For this reason, the library code shouldn’t change exit-handler; only the application knows what to do when it exits.

Another useful case is when you want to call a third-party code which calls exit inside. In that case you may swap the exit-handler for the one that raises a non-error exception while calling the third-party code. Non-error exception isn’t caught in exit, effectively interrupts the steps explained above. (Yet the after thunks of dynamic handlers are processed just like normal exception handling case.) Your application code can then capture the exception. You can use parameterize to swap exit-handler dynamically and thread-safely (see Parameters).

(guard (e [(eq? e 'exit-called) (handle-exit-as-desired)])
  (parameterize ((exit-handler (lambda (c f a) (raise 'exit-called))))
    (call-third-party-library)))

Generally, calling exit while other threads are running should be avoided, since it only rewinds the dynamic handlers active in the calling threads, and other threads will be killed abruptly. If you have to do so for some reason, you may be able to use exit-handler to tell to other threads that the application is exiting. (There’s no general way, and Gauche doesn’t even have a list of all running threads; it’s application’s responsibility).

Note on design: Some languages integrates exit handling into exception handling, treating exit as a kind of exception. It is a tempting idea, so much that we’ve tried it. It didn’t work out well in Gauche; a big annoyance was that when an after thunk raised an exception during rewinding dynamic-winds, it shadowed the original exit exception.

Parameter: exit-handler

A parameter that holds an exit handler, a procedure to be called when exit is called. It takes three arguments, the exit code, the format string and the list of arguments for the format string. See exit above for the details.

Its value can also be #f, in that case, no handler will be called.

The default handler shows the formatted message to the standard error port.

If the handler raises an error, it is captured and discarded. If the handler raises other conditions, it won’t be captured and propagate to outer controls.

Function: sys-exit code

[POSIX] Terminates the current process with the exit code code. If code is #t, the exit code is 0; if it is #f, the exit code is 1; if it is an exact integer, its lower 8 bits is used for the exit code. If code is any other value, exit code is 70 (EX_SOFTWARE). (This is the same as exit).

This procedure calls _exit(2) directly. No cleanup is done. Unflushed file output is discarded.

Function: sys-abort

[POSIX] Calls POSIX abort(). This usually terminates the running process and dumps core. No cleanup is done.


6.24.2 Command-line arguments

The recommended way to get command-line arguments passed to a Scheme script is the argument to the main procedure (see Writing Scheme scripts). For the convenience, there are a few ways to access to the command-line arguments globally.

Note that a Scheme code may not always be called with a command-line argument—for example, an application-embedded Scheme scriptlet may not have the concept of command-line at all. That’s why the main argument is preferred, since it is an explicit interface; if main is called, the caller is responsible to pass in something.

That said, here are how to access the command-line arguments:

Parameter: command-line

[R7RS+ process-context][SRFI-193] When called without arguments, it returns a list of command-line arguments, including the program name in the first element, as a list of strings.

When Gauche is used as an embedded language, it is application’s discretion to set up this parameter. If the application does nothing, this parameter will have an empty list. When you use this parameter in the library you have to deal with that situation.

When called with one argument, a list of string, it will become the new value of the parameter. You can use parameterize to switch the value of command-line dynamically (see Parameters). Note that R7RS only defines zero-argument command-line.

Parameter: script-file

[SRFI-193] While a Scheme program is run as a script, this parameter holds the absolute path of the Scheme source file being run. Run as a script means either it is passed as the script file to gosh, or the file is directly loaded from the toplevel REPL.

If this function is called from the context outside of script execution, #f is returned.

Variable: *program-name*
Variable: *argv*

Deprecated. These variables are bound to the program name and the list of command-line arguments, respectively. In Gauche scripts that are invoked by gosh command, *program-name* is usually the name of the script, as given to gosh. When gosh is invoked interactively, *program-name* contains a zero-length string "", and *argv* is an empty list.

These variables exist in user module.

They are mainly kept for the backward compatibility. These names are compatible to STk, but other Scheme implementation uses different conventions. The command-line parameter above is preferred.

When Gauche is used as an embedded language, it’s the host application’s discretion to set up these variables. Generally, you can’t count on those variables to exist. That’s another reason you should avoid using them.


6.24.3 Environment inquiry

Function: sys-getenv name

[POSIX] Returns the value of the environment variable name as a string, or #f if the environment variable is not defined.

For the portable code, you may want to use SRFI-98’s get-environment-variable (see srfi.98 - Accessing environment variables), which is also in R7RS.

Note: Most systems doesn’t guarantee thread-safety of getenv while environment is being modified; however, Gauche mutexes environment accessing/mutating APIs internally, so you don’t need to worry about the race condition as far as you use Gauche procedures.

Function: sys-environ

Returns the current environment as a list of strings. Each string is a form of NAME=VALUE, where NAME is the name of the environment variable and VALUE is its value. NAME never contains a character #\=. This is useful when you want to obtain the all environment variables of the current process. Use sys-getenv if you want to query a specific environment variable.

Function: sys-environ->alist :optional envlist

A convenience procedure for sys-environ. When the list of environment strings (like what sys-environ returns) is given to envlist, this procedure splits name and value of each environment variable and returns an assoc list.

When envlist is omitted, this procedure calls sys-environ to get the current environment variables.

For the portable code, you may want to use SRFI-98’s get-environment-variables (see srfi.98 - Accessing environment variables), which is also in R7RS.

(sys-environ->alist '("A=B" "C=D=E"))
  => (("A" . "B") ("C" . "D=E"))
Function: sys-setenv name value :optional overwrite
Function: sys-putenv name=value

sys-setenv inserts an environment variable name with the value value. Both name and value must be a string. If the optional argument overwrite is #f (default), the environment is untouched if a variable with name already exists. If overwrite is true, the variable is overwritten.

For sys-putenv, you have to give a single string with the form of NAME=VALUE, that is, concatenating name and value with #\=. If the environment variable with the same name exists, it will be overwritten.

These API reflects POSIX setenv(3) and putenv(3). However, unlike putenv(3), modifying the string passed to sys-putenv afterwards won’t affect the environment.

These procedures are only available when a feature identifier gauche.sys.setenv exists. Use cond-expand (see Feature conditional) to check their availability.

(cond-expand
 [gauche.sys.setenv
   ... use sys-setenv or sys-putenv ... ]
 [else
   ... fallback code ...])

These procedures are thread-safe as far as you access and modify the environment through Gauche API.

Function: sys-unsetenv name
Function: sys-clearenv

Remove the environment variable with name (sys-unsetenv), or all environment variables. sys-clearenv is handy when you need to run subprocess, but you cannot trust the inherited environment.

These procedures are only available when a feature identifier gauche.sys.unsetenv exists. Use cond-expand (see Feature conditional) to check their availability.

(cond-expand
 [gauche.sys.unsetenv
   ... use sys-unsetenv or sys-clearenv ... ]
 [else
   ... fallback code ...])

SRFI-98 (see srfi.98 - Accessing environment variables) also defines a subset of above procedures to access to the environment variables. Portable programs may want to use them instead.

Function: gauche-version
Function: gauche-architecture
Function: gauche-library-directory
Function: gauche-architecture-directory
Function: gauche-site-library-directory
Function: gauche-site-architecture-directory

These functions returns a string that tells information about Gauche runtime itself.

Function: version-alist

[SRFI-176] Returns an alist of various runtime information. The information is the same as what displayed with gosh -V.

The result is affected by the value of the environemnt variable GAUCHE_VERSION_INFO_EXCLUSION. See Environment variables, for details.

Function: sys-available-processors

Returns the number of available processors on the running platform. Return value is always a positive exact integer. If Gauche can’t get the information, 1 is returned.

However, If an environment variable GAUCHE_AVAILABLE_PROCESSORS is defined and its value can be interpreted as a positive integer, then the value is returned regardless of what the hardware/OS tells.


6.24.4 Filesystems

System calls that deal with filesystems. See also file.util - Filesystem utilities, which defines high-level APIs on top of the procedures described here.


6.24.4.1 Directories

See also Directory utilities for high-level API.

Function: sys-readdir path

path must be a string that denotes valid pathname of an existing directory. This function returns a list of strings of the directory entries. The returned list is not sorted. An error is signaled if path doesn’t exists or is not a directory.

Function: glob pattern :key separator folder sorter
Function: sys-glob pattern :key separator folder sorter

Provides a traditional Unix glob(3) functionality; returns a list of pathnames that matches the given pattern.

This feature used to be a wrapper of system-provided glob function, hence it was named sys-glob. However, as of Gauche version 0.8.12, it was reimplemented in Scheme on top of other system calls, to overcome incompatibilities between platforms and for the opportunity to put more functionalities. So we renamed it glob. The old name sys-glob is kept for compatibility, but new programs should use glob.

The pattern argument may be a single glob pattern, or a list of glob patterns. If a list is given, pathnames that matches any one of the pattern are returned. If you’re a unix user, you already know how it works.

gosh> (glob "*.scm")
("ext.scm" "test.scm")
gosh> (glob "src/*.[ch]")
("src/ext.c" "src/ext.h")
gosh> (glob '("*.scm" "src/*.c"))
("ext.scm" "src/ext.c" "test.scm")

Unlike shell’s glob, if there’s no matching pathnames, () is returned.

By default, the result is sorted using built-in sort procedure (see Sorting and merging). You can pass alternative procedure to sorter argument; it should be a procedure that takes single list, and returns a sorted list. It can also be #f, in which case the result isn’t sorted at all.

In fact, globbing is a very useful tool to search hierarchical data structure in general, not limited to the filesystems. So the glob function is implemented separately from the filesystem. Using keyword arguments, you can glob from any kind of tree data structure. It is just that their default values are set to look at the filesystems.

The separator argument should be a char-set, and used to split the pattern into components. Its default is #[/]. It is not used to the actual pathnames to match.

The folder is a procedure that walks through the data structure. It is called with five arguments:

(folder proc seed parent regexp non-leaf?)

proc is a procedure that takes two arguments. The folder should call proc with every node in the parent whose component name matches regexp, passing around the seed value just like fold. It should return the final value returned by proc. For example, if cons is given to proc and () is given to seed, the return value of the folder is a list of nodes that matches the regexp.

The representation of a node is up to the implementation of folder. It can be a pathname, or some sort of objects, or anything. The glob procedure does not care what it is; the glob procedure merely passes the node to subsequent call to folder as parent argument, or returns a list of nodes as the result.

The parent argument is basically a node, and folder traverses its children to find the match. The exception is the initial call of folder— at the beginning glob knows nothing about each node. When glob needs to match an absolute path, it passes #t, and when glob needs to match a relative path, it passes #f, as the initial parent value.

The regexp argument is used to filter the child nodes. It should be matched against the component name of the child, not including its directory names. As a special case, it can be a symbol dir?; if that’s the case, the folder should return node itself, but it may indicate node as a directory; e.g. if node is represented as a pathname, the folder returns a pathname with trailing directory separator. As special cases, if node is a boolean value and regexp is dir?, the folder should return the node representing root node or current node, respectively; e.g. if node is represented as a pathname, the folder may return "/" and "./" for those cases.

The non-leaf argument is a boolean flag. If it is true, the filter should omit the leaf nodes from the result (e.g. only include the directories).

Now, here’s the precise spec of glob pattern matching.

Each glob pattern is a string to match pathname-like strings.

A pathname-like string is a string consists of one or more components, separated by separators. The default separator is #[/]; you can change it with separator keyword argument. A component cannot contain separators, and cannot be a null string. Consecutive separators are regarded as a single separator. A pathname-like string optionally begins with, and/or ends with a separator character.

A glob pattern also consists of components and separator characters. In a component, following characters/syntax have special meanings.

*

When it appears at the beginning of a component, it matches zero or more characters except a period (.). And it won’t match if the component of the input string begins with a period.

Otherwise, it matches zero or more sequence of any characters.

**

If a component is just **, it matches zero or more number of components that match *. For example, src/**/*.h matches all of the following patterns.

src/*.h
src/*/*.h
src/*/*/*.h
src/*/*/*/*.h
...
?

When it appears at the beginning of a component, it matches a character except a period (.). Otherwise, it matches any single character.

[chars]

Specifies a character set. Matches any one of the set. The syntax of chars is the same as Gauche’s character set syntax (see Character Sets). For the compatibility of the traditional glob, the ! character can be used to complement the character set, e.g. [!abc] is the same as [^abc].

\

Include the next character literally in the pattern. This can be used to include above special characters in the pattern.

Function: glob-fold pattern proc seed :key separator folder sorter

This is actually a low-level construct of the glob function. Actually, glob is simply written like this:

(define (glob patterns . opts)
  (apply glob-fold patterns cons '() opts))

The meaning of pattern, separator, folder and sorter is the same as explained above.

For each pathname that matches pattern, glob-fold calls proc with the pathname and a seed value. The initial seed value is seed, and the value proc returns becomes the next seed value. The result of the last call to proc becomes the result of glob-fold. If there’s no matching pathnames, proc is never called and seed is returned.

Function: make-glob-fs-fold :key root-path current-path

This is a utility function to generate a procedure suitable to pass the folder keyword argument of glob-fold and glob. Without arguments, this returns the same procedure which is used in glob-fold and glob by default.

The keyword arguments root-path and current-path specify the paths where glob-fold starts to search.

gosh> (glob "/tmp/*.scm")
("/tmp/x.scm" "/tmp/y.scm")
gosh> (glob "/*.scm"
            :folder (make-glob-fs-fold :root-path "/tmp"))
("/tmp/x.scm" "/tmp/y.scm")
gosh> (glob "*.scm"
            :folder (make-glob-fs-fold :current-path "/tmp"))
("/tmp/x.scm" "/tmp/y.scm")

See File stats, to check if a path is actually a directory.


6.24.4.2 Directory manipulation

Function: sys-remove filename

[POSIX] If filename is a file it is removed. On some systems this may also work on an empty directory, but portable scripts shouldn’t depend on it.

Function: sys-rename old new

[POSIX] Renames a file old to new. The new name can be in different directory from the old name, but both paths must be on the same device.

Function: sys-tmpnam

[POSIX] Creates a file name which is supposedly unique, and returns it. This is in POSIX, but its use is discouraged because of potential security risk. Use sys-mkstemp below if possible.

Function: sys-mkstemp template

Creates and opens a file that has unique name, and returns two values; opened port and the created filename. The file is created exclusively, avoiding race conditions. template is used as the prefix of the file. Unlike Unix’s mkstemp, you don’t need padding characters. The file is opened for writing, and its permission is set to 600.

Function: sys-mkdtemp template

Creates a directory that has unique name, and returns the name. template is used as the prefix of the directory. Unlike Unix’s mkdtemp, you don’t need padding characters. The directory’s permission is set to 700.

[POSIX] Creates a hard link named new to the existing file existing.

[POSIX] Removes pathname. It can’t be a directory. Returns #t if it is successfully removed, or #f if pathname doesn’t exist. An error is signaled otherwise.

There are similar procedures, delete-file/remove-file in file.util module, while they raises an error when the named pathname doesn’t exist (see File operations).

R7RS defines delete-file, which you may want to use in portable programs.

Creates a symbolic link named new to the pathname existing. On systems that doesn’t support symbolic links, this function is unbound.

If a file specified by path is a symbolic link, its content is returned. If path doesn’t exist or is not a symbolic link, an error is signaled. On systems that don’t support symbolic links, this function is unbound.

Function: sys-mkdir pathname mode

[POSIX] Makes a directory pathname with mode mode. (Note that mode is masked by the current umask; see sys-umask below). The parent directory of pathname must exist and be writable by the process. To create intermediate directories at once, use make-directory* in file.util (Directory utilities).

Function: sys-rmdir pathname

[POSIX] Removes a directory pathname. The directory must be empty. To remove a directory with its contents, use remove-directory* in file.util (Directory utilities).

Function: sys-umask :optional mode

[POSIX] Sets umask setting to mode. Returns previous umask setting. If mode is omitted or #f, just returns the current umask without changing it. See man umask for more details.


6.24.4.3 Pathnames

See also Pathname utilities, for high-level APIs.

Function: sys-normalize-pathname pathname :key absolute expand canonicalize

Converts pathname according to the way specified by keyword arguments. More than one keyword argument can be specified.

absolute

If this keyword argument is given and true, and pathname is not an absolute pathname, it is converted to an absolute pathname by appending the current working directory in front of pathname.

expand

If this keyword argument is given and true, and pathname begins with ‘~’, it is expanded as follows:

  • If pathname is consisted entirely by “~”, or begins with “~/”, then the character “~” is replaced for the pathname of the current user’s home directory.
  • Otherwise, characters following ‘~’ until either ‘/’ or the end of pathname are taken as a user name, and the user’s home directory is replaced in place of it. If there’s no such user, an error is signaled.
canonicalize

Tries to remove pathname components “.” and “..”. The pathname interpretation is done purely in textural level, i.e. it doesn’t access filesystem to see the conversion reflects the real files. It may be a problem if there’s a symbolic links to other directory in the path.

Function: sys-basename pathname
Function: sys-dirname pathname

sys-basename returns a basename, that is the last component of pathname. sys-dirname returns the components of pathname but the last one. If pathname has a trailing ‘/’, it is simply ignored.

(sys-basename "foo/bar/bar.z") ⇒ "bar.z"
(sys-basename "coo.scm") ⇒ "coo.scm"
(sys-basename "x/y/") ⇒ "y"
(sys-dirname "foo/bar/bar.z") ⇒ "foo/bar"
(sys-dirname "coo.scm") ⇒ "."
(sys-dirname "x/y/") ⇒ "x"

These functions doesn’t check if pathname really exists.

Some boundary cases:

(sys-basename "") ⇒ ""
(sys-dirname "") ⇒ "."

(sys-basename "/") ⇒ ""
(sys-dirname "/") ⇒ "/"

Note: The above behavior is the same as Perl’s basename and dirname. On some systems, the command basename may return "/" for the argument "/", and "." for the argument ".".

Function: sys-realpath pathname

sys-realpath returns an absolute pathname of pathname that does not include “.”, “..” or symbolic links. If pathname does not exist, it includes a dangling symbolic link, or the caller doesn’t have enough permission to access to the path, an error is signaled.

Note: the POSIX realpath(3) function is known to be unsafe, so Gauche avoids using it and implements sys-realpath in its own.

Function: sys-tmpdir

Returns the default directory name suitable to put temporary files.

On Unix-like systems, the environment variable TMPDIR and TMP are first checked, then falls back to /tmp.

On Windows-native systems, it uses GetTempPath Windows API. It checks environment variables TMP, TEMP, and USERPROFILE in this order, and falls back to Windows system directory.

On both platforms, the returned pathname may not exist, or may not be writable by the calling process.

In general, user programs and libraries are recommended to use temporary-directory (see Directory utilities) instead; sys-tmpdir should be used only if you now the raw value the platform provides.


6.24.4.4 File stats

See also File attribute utilities, for high-level APIs.

Function: file-exists? path

[R7RS file] Returns true if path exists.

Function: file-is-regular? path
Function: file-is-directory? path

Returns true if path is a regular file, or is a directory, respectively. They return false if path doesn’t exist at all.

Builtin Class: <sys-stat>

An object that represents struct stat, attributes of an entry in the filesystem. It has the following read-only slots.

Instance Variable of <sys-stat>: type

A symbol represents the type of the file.

regulara regular file
directorya directory
charactera character device
blocka block device
fifoa fifo
symlinka symbolic link
socketa socket

If the file type is none of the above, #f is returned.

Note: Some operating systems don’t have the socket file type and returns fifo for socket files. Portable programs should check both possibilities to see if the given file is a socket.

Instance Variable of <sys-stat>: perm

An exact integer for permission bits of struct stat. It is the same as lower 9-bits of "mode" slot; provided for the convenience.

Instance Variable of <sys-stat>: mode
Instance Variable of <sys-stat>: ino
Instance Variable of <sys-stat>: dev
Instance Variable of <sys-stat>: rdev
Instance Variable of <sys-stat>: uid
Instance Variable of <sys-stat>: gid
Instance Variable of <sys-stat>: size

An exact integer for those information of struct stat.

Instance Variable of <sys-stat>: atime
Instance Variable of <sys-stat>: mtime
Instance Variable of <sys-stat>: ctime

A number of seconds since Unix Epoch for those information of struct stat.

Instance Variable of <sys-stat>: atim
Instance Variable of <sys-stat>: mtim
Instance Variable of <sys-stat>: ctim

Timestamps represented in <time> object (see Time). If the system supports it, this allows up to nanosecond precision.

Function: sys-stat path
Function: sys-fstat port-or-fd

[POSIX] Returns a <sys-stat> object of path, or the underlying file of port-or-fd, which may be a port or a positive exact integer file descriptor, respectively.

If path is a symbolic link, a stat of the file the link points to is returned from sys-stat.

If port-or-fd is not associated to a file, sys-fstat returns #f.

Function: sys-lstat path

Like sys-stat, but it returns a stat of a symbolic link if path is a symbolic link.

gosh> (describe (sys-stat "gauche.h"))
#<<sys-stat> 0x815af70> is an instance of class <sys-stat>
slots:
  type      : regular
  perm      : 420
  mode      : 33188
  ino       : 845140
  dev       : 774
  rdev      : 0
  nlink     : 1
  uid       : 400
  gid       : 100
  size      : 79549
  atime     : 1020155914
  mtime     : 1020152005
  ctime     : 1020152005
Function: sys-stat->mode stat
Function: sys-stat->ino stat
Function: sys-stat->dev stat
Function: sys-stat->rdev stat
Function: sys-stat->size stat
Function: sys-stat->uid stat
Function: sys-stat->gid stat
Function: sys-stat->atime stat
Function: sys-stat->mtime stat
Function: sys-stat->ctime stat
Function: sys-stat->file-type stat

Deprecated. Use slot-ref to access information of <sys-stat> object.

Function: sys-access pathname amode

[POSIX] Returns a boolean value of indicating whether access of pathname is allowed in amode. This procedure signals an error if used in a suid/sgid program (see the note below). amode can be a combinations (logical or) of following predefined flags.

R_OK

Checks whether pathname is readable by the current user.

W_OK

Checks whether pathname is writable by the current user.

X_OK

Checks whether pathname is executable (or searchable in case pathname is a directory) by the current user.

F_OK

Checks whether pathname exists or not, regardless of the access permissions of pathname. (But you need to have access permissions of the directories containing pathname).

Note: Access(2) is known to be a security hole if used in suid/sgid program to check the real user’s privilege of accessing the file.

Function: sys-chmod path mode
Function: sys-fchmod port-or-fd mode

Change the mode of the file named path or an opened file specified by port-or-fd to mode. mode must be a small positive integer whose lower 9 bits specifies POSIX style permission.

Function: sys-chown path owner-id group-id

Change the owner and/or group of the file named path to owner-id and group-id respectively. owner-id and group-id must be an exact integer. If either of them is -1, the corresponding ownership is not changed.

Function: sys-utime path :optional atime mtime

Change the file’s access time and modification time to atime and mtime, respectively. The arguments can be either #f (indicating the current time), #t (do not change), a real numebr (number of seconds from Epoch), or <time> object (See Time).

See also touch-file (see File operations).


6.24.4.5 Other file operations

Function: sys-chdir dir

[POSIX] An interface to chdir(2). See also current-directory (see Directory utilities).

Function: sys-pipe :key (buffering :line)

[POSIX] Creates a pipe, and returns two ports. The first returned port is an input port and the second is an output port. The data put to the output port can be read from the input port.

Buffering can be :full, :line or :none, and specifies the buffering mode of the ports opened on the pipe. See File ports, for details of the buffering mode. The default mode is sufficient for typical cases.

(receive (in out) (sys-pipe)
  (display "abc\n" out)
  (flush out)
  (read-line in)) ⇒ "abc"

Note: the returned value is changed from version 0.3.15, in which sys-pipe returned a list of two ports.

Function: sys-mkfifo path mode

[POSIX] creates a fifo (named pipe) with a name path and mode mode. Mode must be a positive exact integer to represent the file mode.

Function: sys-isatty port-or-fd

[POSIX] port-or-fd may be a port or an integer file descriptor. Returns #t if the port is connected to the console, #f otherwise.

Function: sys-ttyname port-or-fd

[POSIX] port-or-fd may be a port or an integer file descriptor. Returns the name of the terminal connected to the port, or #f if the port is not connected to a terminal.

Function: sys-truncate path length
Function: sys-ftruncate port-or-fd length

[POSIX] Truncates a regular file named by path or referenced by port-or-fd to a size of length bytes. If the file is larger than length bytes, the extra data is discarded. If the file is smaller than that, zero is padded.


6.24.5 Unix groups and users

Unix groups

Builtin Class: <sys-group>

Unix group information. Has following slots.

Instance Variable of <sys-group>: name

Group name.

Instance Variable of <sys-group>: gid

Group id.

Instance Variable of <sys-group>: passwd

Group password.

Instance Variable of <sys-group>: mem

List of user names who are in this group.

Function: sys-getgrgid gid
Function: sys-getgrnam name

[POSIX] Returns <sys-group> object from an integer group id gid or a group name name, respectively. If the specified group doesn’t exist, #f is returned.

Function: sys-gid->group-name gid
Function: sys-group-name->gid name

Convenience function to convert between group id and group name.

Unix users

Builtin Class: <sys-passwd>

Unix user information. Has following slots.

Instance Variable of <sys-passwd>: name

User name.

Instance Variable of <sys-passwd>: uid

User ID.

Instance Variable of <sys-passwd>: gid

User’s primary group id.

Instance Variable of <sys-passwd>: passwd

User’s (encrypted) password. If the system uses the shadow password file, you just get obscure string like "x".

Instance Variable of <sys-passwd>: gecos

Gecos field.

Instance Variable of <sys-passwd>: dir

User’s home directory.

Instance Variable of <sys-passwd>: shell

User’s login shell.

Instance Variable of <sys-passwd>: class

User’s class (only available on some systems).

Function: sys-getpwuid uid
Function: sys-getpwnam name

[POSIX] Returns <sys-passwd> object from an integer user id uid or a user name name, respectively. If the specified user doesn’t exist, #f is returned.

Function: sys-uid->user-name uid
Function: sys-user-name->uid name

Convenience functions to convert between user id and user name.

Password encryption

Function: sys-crypt key salt

This is the interface to crypt(3). Key and salt must be a string, and an encrypted string is returned. On systems where crypt(3) is not available, call to this function signals an error.

This routine is only for the code that needs to check password against the system’s password database. If you are building user database on your own, you must use crypt.bcrypt module (see crypt.bcrypt - Password hashing) instead of this routine.


6.24.6 Locale

Function: sys-setlocale category locale

[POSIX] Sets/gets the locale of the category category to the locale locale. category must be an exact integer; the following pre-defined variables are available. locale must be a string locale name, or #f if you’re merely querying the current locale.

Returns the locale name on success, or #f if the system couldn’t change the locale. If you pass #f to the locale, it returns the current locale name without changing it.

Variable: LC_ALL
Variable: LC_COLLATE
Variable: LC_CTYPE
Variable: LC_MONETARY
Variable: LC_NUMERIC
Variable: LC_TIME

Predefined variables for possible category value of sys-setlocale.

Function: sys-localeconv

[POSIX] Returns an assoc list of various information for formatting numbers in the current locale.

An example session. It may differ on your system settings.

(sys-localeconv)
 ⇒
   ((decimal_point . ".") (thousands_sep . "")
    (grouping . "") (int_curr_symbol . "")
    (currency_symbol . "") (mon_decimal_point . "")
    (mon_thousands_sep . "") (mon_grouping . "")
    (positive_sign . "") (negative_sign . "")
    (int_frac_digits . 127) (frac_digits . 127)
    (p_cs_precedes . #t) (p_sep_by_space . #t)
    (n_cs_precedes . #t) (n_sep_by_space . #t)
    (p_sign_posn . 127) (n_sign_posn . 127))

(sys-setlocale LC_ALL "fr_FR")
 ⇒ "fr_FR"

(sys-localeconv)
 ⇒
  ((decimal_point . ",") (thousands_sep . "")
   (grouping . "") (int_curr_symbol . "FRF ")
   (currency_symbol . "F") (mon_decimal_point . ",")
   (mon_thousands_sep . " ") (mon_grouping . "\x03\x03")
   (positive_sign . "") (negative_sign . "-")
   (int_frac_digits . 2) (frac_digits . 2)
   (p_cs_precedes . #f) (p_sep_by_space . #t)
   (n_cs_precedes . #f) (n_sep_by_space . #t)
   (p_sign_posn . 1) (n_sign_posn . 1))

6.24.7 Signal

Gauche can send out operating system’s signals to the other processes (including itself) and can handle the incoming signals.

In multithread environment, all threads share the signal handlers, and each thread has its own signal mask. See Signals and threads, for details.

When a system call is interrupted by a signal, and a programmer defines a handler for the signal that doesn’t transfer control to other context, the system call is restarted after the handler returns by default.

Here are some calls that are not simply restarted by signal interruption.

close

This may be called through sys-close, close-port, or even implicitly when the underlying file is closed. When a signal interrupts this call, the passed fd is no longer in use. Simply restarting it can be a race if another thread just grabs the fd.

dup2

This is called via port-fd-dup!. When dup2 returns EINTR, the newfd is no longer in use and some other thread may grab it before restarting it.

sleep
nanosleep

These calls tells the remaining time when they are interrupted. We restart them with that remaining time, not the original argument, so that the total sleep time would be close to what was given originally.

On Windows native platforms, signals don’t work except some limited support of sys-kill.


6.24.7.1 Signals and signal sets

Each signal is referred by its signal number (a small integer) defined on the underlying operating system. Variables are pre-defined to the system’s signal number. System’s signal numbers may be architecture dependent, so you should use those variables rather than using literal integers.

Variable: SIGABRT
Variable: SIGALRM
Variable: SIGCHLD
Variable: SIGCONT
Variable: SIGFPE
Variable: SIGHUP
Variable: SIGILL
Variable: SIGINT
Variable: SIGKILL
Variable: SIGPIPE
Variable: SIGQUIT
Variable: SIGSEGV
Variable: SIGSTOP
Variable: SIGTERM
Variable: SIGTSTP
Variable: SIGTTIN
Variable: SIGTTOU
Variable: SIGUSR1
Variable: SIGUSR2

These variables are bound to the signal numbers of POSIX signals.

Variable: SIGTRAP
Variable: SIGIOT
Variable: SIGBUS
Variable: SIGSTKFLT
Variable: SIGURG
Variable: SIGXCPU
Variable: SIGXFSZ
Variable: SIGVTALRM
Variable: SIGPROF
Variable: SIGWINCH
Variable: SIGPOLL
Variable: SIGIO
Variable: SIGPWR

These variables are bound to the signal numbers of system-dependent signals. Not all of them may be defined on some systems.

For portable code, you can use SRFI-238’s codeset (see srfi.238 - Codesets).

Besides each signal numbers, you can refer to a set of signals using a <sys-sigset> object. It can be used to manipulate the signal mask, and to install a signal handler to a set of signals at once.

Function: sys-strsignal signum

[POSIX] Interface to strsignal(3). The argument must be an exact integer.

Returns the system message associated with the signal with the number signum, as a string. if no such message is available, or signum is not a valid signal number, this function may return #f or some generic message provided by the system.

For portable code, you can use SRFI-238’s codeset (see srfi.238 - Codesets).

Class: <sys-sigset>

A set of signals. An empty sigset can be created by

(make <sys-sigset>) ⇒ #<sys-sigset []>
Function: sys-sigset signal …

Creates and returns an instance of <sys-sigset> with members signal …. Each signal may be either a signal number, another <sys-sigset> object, or #t for all available signals.

(sys-sigset SIGHUP SIGINT) ⇒ #<sys-sigset [HUP|INT]>
Function: sys-sigset-add! sigset signal …
Function: sys-sigset-delete! sigset signal …

Sigset must be a <sys-sigset> object. Those procedures adds and removes the specified signals from sigset respectively, and returns the result. sigset itself is also modified.

signal may be either a signal number, another <sys-sigset> object, or #t for all available signals.

Function: sys-sigset-fill! sigset
Function: sys-sigset-empty! sigset

Fills sigset by all available signals, or empties sigset.

Function: sys-signal-name signal

Returns the human-readable name of the given signal number. (Note that signal numbers are system-dependent.)

For portable code, you can use SRFI-238’s codeset (see srfi.238 - Codesets).

(sys-signal-name 2) ⇒ "SIGINT"

6.24.7.2 Sending signals

To send a signal, you can use sys-kill which works like kill(2).

Function: sys-kill pid sig

[POSIX] Sends a signal sig to the specified process(es). Sig must be a positive exact integer. pid is an exact integer and specifies the target process(es):

  • If pid is positive, it is the target process id.
  • If pid is zero, the signal is sent to every process in the process group of the current process.
  • If pid is less than -1, the signal is sent to every process in the process group -pid.

On Windows native platforms, sys-kill may take positive integer or a process handle (<win:handle> instance) as pid. Only SIGKILL, SIGINT and SIGABRT are allowed as sig; Gauche uses TerminateProcess to terminate the target process for SIGKILL, and sends the target process CTRL_C_EVENT and CTRL_BREAK_EVENT for SIGINT and SIGABRT, respectively.

There’s no Scheme equivalence for raise(), but you can use (sys-kill (sys-getpid) sig).


6.24.7.3 Handling signals

You can register signal handling procedures in Scheme. (In multithread environment, signal handlers are shared by all threads; see Signals and threads for details).

When a signal is delivered to the Scheme process, the VM just records it and processes it later at a ’safe point’ where the state of VM is consistent. We call the signal is pending when it is registered by the VM but not processed yet.

(Note that this makes handling of some signals such as SIGILL useless, for the process can’t continue sensible execution after recording the signal).

If the same signal is delivered more than once before VM processes the first one, the second one and later have no effect. (This is consistent to the traditional Unix signal model.) In other words, for each VM loop a signal handler can be invoked at most once per each signal.

When too many signals of the same kind are pending, Gauche assumes something has gone wrong (e.g. infinite loop inside C-routine) and aborts the process. The default of this limit is set rather low (3), to allow unresponsive interactive script to be terminated by typing Ctrl-C three times. Note that the counter is individual for each signal; Gauche won’t abort if one SIGHUP and two SIGINTs are pending, for example. You can change this limit by set-signal-pending-limit described below.

When you’re using the gosh interpreter, the default behavior for each signal is as in the following table.

SIGABRT, SIGILL, SIGKILL, SIGSTOP, SIGSEGV, SIGBUS

Cannot be handled in Scheme. Gosh follows the system’s default behavior.

SIGCHLD, SIGTSTP, SIGTTIN, SIGTTOU, SIGWINCH

No signal handles are installed for these signals by gosh, so the process follows the system’s default behavior. A Scheme programs can install its own signal handler if necessary.

SIGCONT

If gosh is running with input editing mode, a signal handler is installed to restore terminal status. Otherwise, no signal handler is installed by default, and a Scheme program can install its own signal handler if necessary.

SIGHUP, SIGQUIT, SIGTERM

Gosh installs a signal handler for these signals that exits from the application with code 0.

SIGPIPE

Gosh installs a signal handler that does nothing—that is, this signal is effectively ignored by default.

It is a design choice. Since Gauche delays actual handling of signals, SIGPIPE would be handled after the system call that tries to write to a broken pipe returns with EPIPE. That makes the signal a lot less useful, for we can handle the situation with error handlers for <system-error> with EPIPE.

The default Unix behavior of SIGPIPE is to terminate the process. It is useful for the traditional command-line tools that are often piped together—if one of downstream commands fails, the upstream process receives SIGPIPE and the entire command chain is shut down without a fuss. The signal is, however, rather an annoyance for other types of output such as sockets.

Gauche does support this “exit when pipe gets stuck” convention by ports. A port can be configured as sigpipe sensitive; if writing to that port caused EPIPE, it terminates the process. By default, standard output and standard error output are configured in that way.

SIGPWR, SIGXCPU, SIGUSR1, SIGUSR2

On Linux platforms with thread support, these signals are used by the system and not available for Scheme. On other systems, these signals behaves the same as described below.

other signals

Gosh installs the default signal handler, which raises <unhandled-signal-error> condition (see Conditions). Scheme programs can override it by its own signal handler.

If you’re using Gauche embedded in some other application, it may redefine the default behavior.

Use the following procedures to get/set signal handlers from Scheme.

Function: set-signal-handler! signals handler :optional sigmask

Signals may be a single signal number or a <sys-sigset> object, and handler should be either #t, #f, #<undef>, or a procedure that takes one argument. If handler is a procedure, it will be called when the process receives one of specified signal(s), with the received signal number as an argument.

By default, the signals in signals are blocked (in addition to the signal mask in effect at that time) during handler is executed, so that handler won’t be reentered by the same signal(s). You can provide a <sys-sigset> object to the sigmask arg to specify the signals to be blocked explicitly. Note that the signal mask is per-thread; if more than one thread unblocks a signal, the handler may still be invoked during execution of the handler (in other thread) even if you specify sigmask. You have to set the threads’ signal mask properly to avoid such situation.

It is safe to do anything in handler, including throwing an error or invoking continuation captured elsewhere. (However, continuations captured inside handler will be invalid once you return from handler).

If handler is #t, the operating system’s default behavior is set to the specified signal(s). If handler is #f, the specified signals(s) will be ignored.

If handler is #<undef> (see Undefined values), it indicates Gauche to leave the current OS’s signal handler as it is. This value isn’t as much use in set-signal-handler! as in get-signal-handler: If #<undef> is passed to set-signal-handler!, it immediately returns without modifying anything. However, if you get #<undef> from get-signal-handler, you can know that the signal handler behavior hasn’t been modified by Gauche. (Note that once Gauche ever installs a signal handler, there is no way to revert back to make get-signal-handler return #<undef>).

Note that signal handler setting is shared among threads in multithread environment. The handler is called from the thread which is received the signal. See Signals and threads for details.

Function: get-signal-handler signum
Function: get-signal-handler-mask signum

Returns the handler setting, or signal mask setting, of a signal signum, respectively. See set-signal-handler! for the meaning of the return value of get-signal-handler.

Function: get-signal-handlers

Returns an associative list of all signal handler settings. Car of each element of returned list is a <sys-sigset> object, and cdr of it is the handler (a procedure or a boolean value) of the signals in the set.

Function: get-signal-pending-limit
Function: set-signal-pending-limit limit

Gets/sets the maximum number of pending signals per each signal type. If the number of pending signals exceeds this limit, Gauche aborts the process. See the explanation at the beginning of this section for the details. Limit must be a nonnegative exact integer. In the current implementation the maximum number of limit is 255. Setting limit to zero makes the number of pending signals unlimited.

Macro: with-signal-handlers (handler-clause …) thunk

A convenience macro to install signal handlers temporarily during execution of thunk. (Note: though this is convenient, this has certain dangerous properties described below. Use with caution.)

Each Handler-clause may be one of the following forms.

(signals expr …)

Signals must be an expression that will yield either a signal, a list of signals, or a <sys-sigset> object. Installs a signal handler for signals that evaluates expr … when one of the signals in signals is delivered.

(signals => handler)

This form sets the handler of signals to handler, where handler should be either #t, #f or a procedure that takes one argument.

If handler is a procedure, it will be called when the process receives one of specified signal(s), with the received signal number as an argument. If handler is #t, the operating system’s default behavior is set to the specified signal(s). If handler is #f, the specified signals(s) will be ignored.

When the control exits from thunk, the signal handler setting before with-signal-handlers are recovered.

CAVEAT: If you’re setting more than one signal handlers, they are installed in serial. If a signal is delivered before all the handlers are installed, the signal handler state may be left inconsistent. Also note that the handler setting is a global state; you can’t set "thread local" handler by with-signal-handlers, although the form may be misleading.


6.24.7.4 Masking and waiting signals

A Scheme program can set a signal mask, which is a set of signals to be blocked from delivery. If a signal is delivered which is completely blocked in the process, the signal becomes "pending". The pending signal may be delivered once the signal mask is changed not to block the specified signal. (However, it depends on the operating system whether the pending signals are queued or not.)

In multithread environment, each thread has its own signal mask.

Function: sys-sigmask how mask

Modifies the current thread’s signal mask, and returns the previous signal mask. Mask should be a <sys-sigset> object to specify the new mask, or #f if you just want to query the current mask without modifying one.

If you give <sys-sigset> object to mask, how argument should be one of the following integer constants:

SIG_SETMASK

Sets mask as the thread’s signal mask.

SIG_BLOCK

Adds signals in mask to the thread’s signal mask.

SIG_UNBLOCK

Removes signals in mask from the thread’s signal mask.

Function: sys-sigsuspend mask

Atomically sets thread’s signal mask to mask and suspends the calling thread. When a signal that is not blocked and has a signal handler installed is delivered, the associated handler is called, then sys-sigsuspend returns.

Function: sys-sigwait mask

[POSIX] Mask must be a <sys-sigset> object. If any of signals in mask is/are pending in the OS, atomically clears one of them and returns the signal number of the cleared one. If there’s no signal in mask pending, sys-sigwait blocks until any of the signals in mask arrives.

You have to block all signals in mask in all threads before calling sys-sigwait. If there’s a thread that doesn’t block the signals, the behavior of sys-sigwait is undefined.

Note: Sys-sigwait uses system’s sigwait function, whose behavior is not defined if there’s a signal handler on the signals it waits. To avoid complication, sys-sigwait resets the handlers set to the signals included in mask before calling sigwait to SIG_DFL, and restores them after sigwait returns. If another thread changes signal handlers while sys-sigwait is waiting, the behavior is undefined; you shouldn’t do that.


6.24.7.5 Signals and threads

The semantics of signals looks a bit complicated in the multithread environment. Nevertheless, it is pretty comprehensible once you remember a small number of rules. Besides, Gauche sets up the default behavior easy to use, while allowing programmers to do tricky stuff.

If you don’t want to be bothered by the details, just remember one thing, with one sidenote. By default, signals are handled by the primordial (main) thread. However, if the main thread is suspended on mutex or condition variable, the signal may not be handled at all, so be careful.

Now, if you are curious about the details, here are the rules:

  • The signal handler setting is shared by all threads.
  • The signal mask is thread-specific.
  • If a process receives an asynchronous signal (think it as a signal delivered from other processes), one thread is chosen, out of threads which don’t block that signal.
  • The signal handler is run on the chosen thread. However, if the chosen thread is waiting for acquiring a mutex lock or a condition variable, the handling of signal will be delayed until the thread is restarted. Signal delivery itself doesn’t restart the thread.

Now, these rules have several implications.

If there are more than one thread that don’t block a particular signal, you can’t know which thread receives the signal. Such a situation is much less useful in Gauche than C programs because of the fact that the signal handling can be delayed indefinitely if the receiver thread is waiting on mutex or condition variable. So, it is recommended to make sure, for each signal, there is only one thread that can receive it.

In Gauche, all threads created by make-thread (see Thread procedures) blocks all the signals by default (except the reserved ones). This lets all the signals to be directed to the primordial (main) thread.

Another strategy is to create a thread dedicated for handling signals. To do so, you have to block the signals in the primordial thread, then create the signal-handling thread, and within that thread you unblock all the signals. Such a thread can just loop on sys-pause.

(thread-start!
  (make-thread
    (lambda ()
      (sys-sigmask SIG_SETMASK (make <sys-sigset>)) ;;empty mask
      (let loop () (sys-pause) (loop)))))

Complicated application may want to control per-thread signal handling precisely. You can do so, just make sure that at any moment only the designated thread unblocks the desired signal.


6.24.8 System inquiry

Function: sys-uname

[POSIX] Returns a list of five elements, (sysname nodename release version machine).

Function: sys-gethostname

Returns the host name. If the system doesn’t have gethostname(), the second element of the list returned by sys-uname is used.

Function: sys-getdomainname

Returns the domain name. If the system doesn’t have getdomainname(), "localdomain" is returned.

Function: sys-getcwd

[POSIX] Returns the current working directory by a string. If the current working directory couldn’t be obtained from the system, an error is signaled. See also sys-chdir (see Other file operations), current-directory (see Directory utilities).

Function: sys-getgid
Function: sys-getegid

[POSIX] Returns integer value of real and effective group id of the current process, respectively. Use sys-gid->group-name or sys-getgrgid to obtain the group’s name and other information associated to the returned group id (see Unix groups and users).

Function: sys-setgid gid

[POSIX] Sets the effective group id of the current process.

Function: sys-getuid
Function: sys-geteuid

[POSIX] Returns integer value of real and effective user id of the current process, respectively. Use sys-uid->user-name or sys-getpwuid to obtain the user’s name and other information associated to the returned user id (see Unix groups and users).

Function: sys-setuid uid

[POSIX] Sets the effective user id of the current process.

Function: sys-setugid?

Returns true iff the process is running with suid/sgid-ed (that is, the program’s suid and/or sgid bit is set.)

Note: If the platform has issetugid() call, we use it. Otherwise, we remember whether the real (user|group) id and the effective (user|group) id differ or not at the initialization time. (In the latter case, we can’t detect the case that the process changes [e]uid/[e]gid before initializing Gauche; keep it in mind if libgauche is used as an embedded Scheme engine).

Function: sys-getgroups

[POSIX] Returns a list of integer ids of supplementary groups.

Function: sys-setgroups gids

Sets the current process’s groups to the given list of integer group ids. The caller must have the appropriate privilege.

This procedure is only available when the feature id gauche.sys.setgroups exists. Use cond-expand for the portable program:

(cond-expand
  [gauche.sys.setgroups (sys-setgroups '(0 1))]
  [else])
Function: sys-getlogin

[POSIX] Returns a string of the name of the user logged in on the controlling terminal of the current process. If the system can’t determine the information, #f is returned.

Function: sys-getpgrp

[POSIX] Returns a process group id of the current process.

Function: sys-getpgid pid

Returns a process group id of the process specified by pid. If pid is zero, the current process is used.

Note that getpgid() call is not in POSIX. If the system doesn’t have getpgid(), sys-getpgid still works if pid is zero (it just calls sys-getpgrp), but signals an error if pid is not zero.

Function: sys-setpgid pid pgid

[POSIX] Sets the process group id of the process pid to pgid. If pid is zero, the process ID of the current process is used. If pgid is zero, the process ID of the process specified by pid is used. (Hence sys-setpgid(0, 0) sets the process group id of the current process to the current process id).

Function: sys-setsid

[POSIX] Creates a new session if the calling process is not a process group leader.

Function: sys-getpid
Function: sys-getppid

[POSIX] Returns the current process id and the parent process id, respectively.

Function: sys-times

[POSIX]

Function: sys-ctermid

[POSIX] Returns the name of the controlling terminal of the process. This may be just a "/dev/tty". See also sys-ttyname.

Function: sys-getrlimit resource
Function: sys-setrlimit resource current :optional maximum

[POSIX] Get and set resource limits respectively. Resource is an integer constant to specify the resource of concern. The following constants are defined. (The constants marked as bsd and/or linux indicates that they are not defined in POSIX but defined in BSD and/or Linux. Other systems may or may not have them. Consult getrlimit manpage of your system for the details.)

RLIMIT_AS                      RLIMIT_CORE
RLIMIT_CPU                     RLIMIT_DATA
RLIMIT_FSIZE                   RLIMIT_LOCKS
RLIMIT_MEMLOCK (bsd/linux)     RLIMIT_MSGQUEUE (linux)
RLIMIT_NICE (linux)            RLIMIT_NOFILE
RLIMIT_NPROC (bsd/linux)       RLIMIT_RSS (bsd/linux)
RLIMIT_RTPRIO (linux)          RLIMIT_SIGPENDING (linux)
RLIMIT_SBSIZE                  RLIMIT_STACK
RLIMIT_OFILE
Function: sys-nice inc

[POSIX] Adds inc, which must be an exact integer, to the current process’s nice value. Only the root user can specify negative inc value. Returns the new nice value.

Function: sys-strerror errno

Errno must be an exact nonnegative integer representing a system error number. This function returns a string describing the error.

For portable code, you can use SRFI-238’s codeset (see srfi.238 - Codesets).

To represent errno, the following constants are defined. Each constant is bound to an exact integer representing the system’s error number. Note that the actual value may differ among systems, and some of these constants may not be defined on some systems.

E2BIG             EHOSTDOWN         ENETDOWN          ENXIO
EACCES            EHOSTUNREACH      ENETRESET         EOPNOTSUPP
EADDRINUSE        EIDRM             ENETUNREACH       EOVERFLOW
EADDRNOTAVAIL     EILSEQ            ENFILE            EPERM
EADV              EINPROGRESS       ENOANO            EPFNOSUPPORT
EAFNOSUPPORT      EINTR             ENOBUFS           EPIPE
EAGAIN            EINVAL            ENOCSI            EPROTO
EALREADY          EIO               ENODATA           EPROTONOSUPPORT
EBADE             EISCONN           ENODEV            EPROTOTYPE
EBADF             EISDIR            ENOENT            ERANGE
EBADFD            EISNAM            ENOEXEC           EREMCHG
EBADMSG           EKEYEXPIRED       ENOKEY            EREMOTE
EBADR             EKEYREJECTED      ENOLCK            EREMOTEIO
EBADRQC           EKEYREVOKED       ENOLINK           ERESTART
EBADSLT           EL2HLT            ENOMEDIUM         EROFS
EBFONT            EL2NSYNC          ENOMEM            ESHUTDOWN
EBUSY             EL3HLT            ENOMSG            ESOCKTNOSUPPORT
ECANCELED         EL3RST            ENONET            ESPIPE
ECHILD            ELIBACC           ENOPKG            ESRCH
ECHRNG            ELIBBAD           ENOPROTOOPT       ESRMNT
ECOMM             ELIBEXEC          ENOSPC            ESTALE
ECONNABORTED      ELIBMAX           ENOSR             ESTRPIPE
ECONNREFUSED      ELIBSCN           ENOSTR            ETIME
ECONNRESET        ELNRNG            ENOSYS            ETIMEDOUT
EDEADLK           ELOOP             ENOTBLK           ETOOMANYREFS
EDEADLOCK         EMEDIUMTYPE       ENOTCONN          ETXTBSY
EDESTADDRREQ      EMFILE            ENOTDIR           EUCLEAN
EDOM              EMLINK            ENOTEMPTY         EUNATCH
EDOTDOT           EMSGSIZE          ENOTNAM           EUSERS
EDQUOT            EMULTIHOP         ENOTSOCK          EWOULDBLOCK
EEXIST            ENAMETOOLONG      ENOTTY            EXDEV
EFAULT            ENAVAIL           ENOTUNIQ          EXFULL
EFBIG
Function: sys-errno->symbol k
Function: sys-symbol->errno symbol

These procedures convert between integer error number and the symbol of its unix name (e.g. EINTR).

If the given error number or name isn’t available on the running platform, those procedures return #f. See sys-strerror above for potentially available error names.

Valid error names and their actual values differ among platforms. These procedures make it easy to write portable meta-code that deal with system errors.

For portable code, you can use SRFI-238’s codeset (see srfi.238 - Codesets).


6.24.9 Time

Gauche has two representations of time, one is compatible to POSIX API, and the other is compatible to SRFI-18, SRFI-19 and SRFI-21. Most procedures accept both representations; if not, the representation the procedure accepts is indicated as either ’POSIX time’ or ’SRFI time’.

POSIX time is represented by a real number which is a number of seconds since Unix Epoch (Jan 1, 1970, 0:00:00GMT). Procedure sys-time, which corresponds to POSIX time(2), returns this time representation.

SRFI-compatible time is represented by an object of <time> class, which keeps seconds and nanoseconds, as well as the type of the time (UTC, TAI, duration, process time, etc). Current-time returns this representation.

POSIX time

Function: sys-time

[POSIX] Returns the current time in POSIX time (the time since Epoch (00:00:00 UTC, January 1, 1970), measured in seconds). It may be a non-integral number, depending on the architecture.

Note that POSIX’s definition of “seconds since the Epoch” doesn’t take leap seconds into account.

Function: sys-gettimeofday

Returns two values. The first value is a number of seconds, and the second value is a fraction in a number of microseconds, since 1970/1/1 0:00:00 UTC. If the system doesn’t have gettimeofday call, this function calls time(); in that case, microseconds portion is always zero.

Builtin Class: <sys-tm>

Represents struct tm, a calendar date. It has the following slots.

Instance Variable of <sys-tm>: sec

Seconds. 0-61.

Instance Variable of <sys-tm>: min

Minutes. 0-59.

Instance Variable of <sys-tm>: hour

Hours. 0-23.

Instance Variable of <sys-tm>: mday

Day of the month, counting from 1. 1-31.

Instance Variable of <sys-tm>: mon

Month, counting from 0. 0-11.

Instance Variable of <sys-tm>: year

Years since 1900, e.g. 102 for the year 2002.

Instance Variable of <sys-tm>: wday

Day of the week. Sunday = 0 .. Saturday = 6.

Instance Variable of <sys-tm>: yday

Day of the year. January 1 = 0 .. December 31 = 364 or 365.

Instance Variable of <sys-tm>: isdst

A flag that indicates if the daylight saving time is in effect. Positive if DST is in effect, zero if not, or negative if unknown.

Function: sys-gmtime time
Function: sys-localtime time

[POSIX] Converts time to <sys-tm> object, represented in GMT or local timezone, respectively. Time can be either POSIX-time or SRFI-time.

Function: sys-ctime time

[POSIX] Converts time to it string representation, using POSIX ctime(). Time can be either POSIX-time or SRFI-time.

Function: sys-difftime time1 time0

[POSIX] Returns the difference of two times in the real number of seconds. Time0 and time1 can be either POSIX-time or SRFI-time.

Function: sys-asctime tm

[POSIX] Converts <sys-tm> object tm to a string representation.

Function: sys-strftime format tm

[POSIX] Converts <sys-tm> object tm to a string representation, according to a format string format. See your system’s manual entry of strftime for the supported format.

It may return an empty string if the formatting results in an unusually lengthy string.

Function: sys-mktime tm

[POSIX] Converts <sys-tm> object tm, expressed as local time, to the POSIX-time (number of seconds since Epoch).

Function: sys-tm->alist tm

Deprecated.

SRFI time

Builtin Class: <time>

The <time> object also represents a point of time.

Instance Variable of <time>: type

Indicates time type. time-utc is the default, and that represents the number of seconds since Unix Epoch. SRFI-19 (see srfi.19 - Time data types and procedures) adds more types.

Instance Variable of <time>: second

Second part of the time.

Instance Variable of <time>: nanosecond

Nanosecond part of the time.

Function: current-time

[SRFI-18][SRFI-21] Returns the <time> object representing the current time in time-utc. See srfi.19 - Time data types and procedures, for it redefines current-time to allow optional argument to specify time type.

Function: time? obj

[SRFI-18][SRFI-19][SRFI-21] Returns #t if obj is a time object.

Function: absolute-time obj :optional current-time

The argument must be either a <time> object, a real number, or #f. If it is an absolute <time> object, it specifies an absolute point of time. If it is a <time> object of time-duration type, it is taken as a relative tiem from the current time. If it is a real number, it specifies the number of seconds from the current time.

This procedure returns #f if the argument is #f, and a UTC <time> object for an absolute point of time otherwise.

Most procedures that takes ‘timeout’ argument accepts <time object, real number or #f. This procedure is useful to process such argument in the same way.

The optional current-time is, if provided, must be an absolute <time> object or #f. If it is a <time> object, it is used as the current time instead of the actual current time.

Function: seconds+ time x

[SRFI-226+] Returns a time object that is x seconds after the given time. The type of returned time object is the same as time. The argument x must be a finite real number. If it is negative, returnd time is before the given time.

This procedure is mainly to write code compatibe to SRFI-226. For Gauche-specific code, you can use absolute-time above.

See Time procedures, for another way to compute with time difference by add-duration/subtract-duration.

Function: time->seconds time
Function: seconds->time seconds

[SRFI-18][SRFI-21] Converts between time object and the number of seconds (POSIX-time). Time argument of time->seconds has to be a <time> object.


6.24.10 Process management

The following procedures provide pretty raw, direct interface to the system calls. See also gauche.process - High-level process interface, which provides more convenient process handling on top of these primitives.

Fork and exec

Function: sys-system command

[POSIX] Runs command, which must be a string, in a subprocess. command is usually passed to sh, so the shell metacharacters are interpreted.

If the operating system fails to spawn a subshell, a <system-error> is thrown. Otherwise, it waits until the subshell terminates, and the integer termination status of the subshell is returned.

The termination status must be interpreted as the same way as the return value of sys-wait, described below. For example, if you want to get exit status, you have to test the result with sys-wait-exited?, then apply sys-wait-exit-status.

In general, analyzing the result of sys-system properly is cumbersome, for nonzero code may indicate subshell’s abnormal exit or signalled status or the command’s abnormal exit or signalled status. We recommend to use do-process etc. of gauche.process module if you need to handle subprocess’ exit status (see gauche.process - High-level process interface).

On Windows native platforms this will pass the argument to cmd.exe. We strongly discourage invoking cmd.exe with externally supplied arguments, since it is impossible to safely escape arbitrary string for cmd.exe arguments on Windows.

Function: sys-fork

[POSIX] Fork the current process. Returns 0 if you’re in the child process, and a child process’ pid if you’re in the parent process. All the opened file descriptors are shared between the parent and the child. See fork(2) of your system for details.

If the child process runs some Scheme code and exits instead of calling sys-exec, it should call sys-exit instead of exit to terminate itself. Normal exit call tries to flush the file buffers, and on some OS it messes up the parent’s file buffers.

It should be noted that sys-fork is not safe when multiple threads are running. Because fork(2) copies the process’ memory image which includes any mutex state, a mutex which is locked by another thread at the time of sys-fork remains locked in the child process, nevertheless the child process doesn’t have the thread that unlock it! (This applies to the internal mutexes as well, so even you don’t use Scheme mutex explicitly, this situation can always happen.)

If what you want is to spawn another program in a multi-threaded application, use sys-fork-and-exec explained below. If you absolutely need to run Scheme code in the child process, a typical technique is that you fork a manager process at the beginning of application, and whenever you need a new process you ask the manager process to fork one for you.

This procedure is not available on Windows native platforms.

Function: sys-exec command args :key directory iomap sigmask environment

[POSIX+] Execute command with args, a list of arguments. The current process image is replaced by command, so this function never returns.

All elements of args must be strings. The first element of args is used as argv[0], i.e. the program name.

(NB: On Windows, you can invoke batch files (*.bat, *.cmd) using sys-exec and sys-fork-and-exec, but you can’t use characters ()%!^<>&|" within the command-line arguments, since there’s no comprehensive way to escape them safely. You can pass them if you directly invoke an executable file.)

The keyword argument directory must be a string of a directory name or #f. If it is a string, sys-exec change current working directory there before executing the program.

The iomap keyword argument, when provided, specifies how the open file descriptors are treated. It must be the following format:

((to-fd . from-port-or-fd) ...)

To-fd must be an integer, and from-port-or-fd must be an integer file descriptor or a port. Each element of the list makes the file descriptor of from-port-or-fd of the current process be mapped to the file descriptor to-fd in the executed process.

If iomap is provided, any file descriptors other than specified in the iomap list will be closed before exec(). Otherwise, all file descriptors in the current process remain open.

(sys-exec "ls" '("ls" "-l")) ⇒ ;; ls is executed.

(let ((out (open-output-file "ls.out")))
  (sys-exec "ls" '("ls" "-l") :iomap `((2 . 1) (1 . ,out)))
   ⇒
  ;; ls is executed, with its stderr redirected
  ;; to the current process's stdout, and its
  ;; stdout redirected to the file "ls.out".

The sigmask keyword argument can be an instance of <sys-sigset> or #f (See Signal, for the details of signal masks). If it is an instance of <sys-sigset>, the signal mask of calling thread is replaced by it just before exec(2) is called. It is useful, for example, to run an external program from a thread where all signals are blocked (which is the default; see Signals and threads). Without setting sigmask, the execed process inherits calling thread’s signal mask and become a process that blocks all signals, which is not very convenient in most cases.

Finally, environment keyword argument specifies the environment where the new process sees. If it is #f (default), the new process sees the same enviornment of the caller process. Otherwise, it must be a list of strings. Each string must be a form of "NAME=VALUE", where NAME is the name of envionemnt variable, and VALUE is its value. Environment variable’s name cannot contain =, while its value can. This format is compatible with what sys-environ returns (see Environment inquiry), so that you can get the current enviornment with sys-environ, add/remove/modify some of its entries, and pass it to this argument.

When sys-exec encounters an error, most of the time it raises an error condition. Once the file descriptors are permuted, however, it would be impractical to handle errors in reasonable way (you don’t even know stderr is still available!), so Gauche simply exits on the error.

On Windows native platforms, only redirections of stdin, stdout and stderr are handled. Singal mask is ignored, for Windows doesn’t have signals as the means of interprocess communication.

Function: sys-fork-and-exec command args :key directory iomap sigmask detached environment

Like sys-exec, but executes fork(2) just before remapping I/O, altering signal mask and call execvp(2). Returns child’s process id. The meanings of arguments are the same as sys-exec.

It is strongly recommended to use this procedure instead of sys-fork and sys-exec combination when you need to spawn another program while other threads are running. No memory allocation nor lock acquisition is done between fork(2) and execvp(2), so it’s pretty safe in the multithreaded environment.

On Windows native platforms, this procedure returns a Windows handle object (<win:handle>) of the created process instead of an integer process ID. See below for Windows process handle specific API.

Like sys-exec, only redirections of stdin, stdout and stderr are handled on Windows native platforms.

When a true value is given to the detached keyword argument, the executed process is detached from the current process group and belongs to its own group. That is, it won’t be affected to the signal sent to the process group the caller process currently belongs to. It is a part of the common idioms to start a daemon process.

On Unix platforms, besides the executed process gets its own session by setsid(2), it performs extra fork(2) to make its parent be the init process (pid=1). (Note: It means the running process is actually a grandchild of the calling process, although that relationship isn’t preserved. The returned pid is the running process’s one, not the intermediate process that exits immediately.)

On Windows native platforms, this flag causes the new process to be created with the CREATE_NEW_PROCESS_GROUP creation flag.

Wait

Function: sys-wait

[POSIX] Calls system’s wait(2). The process suspends its execution until one of the child terminates. Returns two exact integer values, the first one is the child’s process id, and the second is a status code. The status code can be interpreted by the following functions.

Function: sys-waitpid pid :key nohang untraced

[POSIX] This is an interface to waitpid(3), an extended version of wait.

pid is an exact integer specifying which child(ren) to be waited. If it is a positive integer, it waits for that specific child. If it is zero, it waits for any member of this process group. If it is -1, it waits for any child process. If it is less than -1, it waits for any child process whose process group id is equal to the absolute value of pid.

If there’s no child process to wait, or a specific pid is given but it’s not a child process of the current process, an error (<system-error>, ECHILD) is signaled.

The calling process suspends until one of those child process is terminated, unless true is specified to the keyword argument nohang.

If true is specified to the keyword argument untraced, the status of stopped child process can be also returned.

The return values are two exact integers, the first one is the child process id, and the second is a status code. If nohang is true and no child process status is available, the first value is zero.

On Windows native platforms, this procedure may also accept a Windows process handle (<win:handle>) object as pid to wait the specific process. You can pass -1 as pid to wait for any children, but you cannot wait for a specific process group.

Function: sys-wait-exited? status
Function: sys-wait-exit-status status

[POSIX] The argument is an exit status returned as a second value from sys-wait or sys-waitpid. sys-wait-exited? returns #t if the child process is terminated normally. sys-wait-exit-status returns the exit code the child process passed to exit(2), or the return value of main().

Function: sys-wait-signaled? status
Function: sys-wait-termsig status

[POSIX] The argument is an exit status returned as a second value from sys-wait or sys-waitpid. sys-wait-signaled? returns #t if the child process is terminated by an uncaught signal. sys-wait-termsig returns the signal number that terminated the child.

Function: sys-wait-stopped? status
Function: sys-wait-stopsig status

[POSIX] The argument is an exit status returned as a second value from sys-waitpid. sys-wait-stopped? returns #t if the child process is stopped. This status can be caught only by sys-waitpid with true untraced argument. sys-wait-stopsig returns the signum number that stopped the child.

On Windows native platforms, exit code is not structured as on Unix. You cannot distinguish a process being exited voluntarily or by forced termination. Gauche uses exit code #xff09 to terminate other process with sys-kill, and the above sys-wait-* procedures are adjusted accordingly, so that sys-wait-signaled? can likely to be used to check whether if the child process is terminated by Gauche. (See Signal, for the details of signal support on Windows.) Sys-wait-stopped? never returns true on Windows native platforms (yet).

Windows specific utilities

The following procedures are to access Windows process handle. They are only available on Windows native platforms.

Function: sys-win-process? obj

[Windows] Returns #t iff obj is a Windows process handle object.

Function: sys-win-process-pid handle

[Windows] Returns an integer PID of the process represented by a Windows process handle handle. An error is signaled if handle is not a valid Windows process handle.

Note that the API to get a pid from a process handle is only provided on or after Windows XP SP1. If you call this procedure on Windows version before that, -1 will be returned.


6.24.11 I/O multiplexing

The interface functions for select(2). The higher level interface is provided on top of these primitives; see gauche.selector - Simple dispatcher.

Builtin Class: <sys-fdset>

Represents fd_set, a set of file descriptors. You can make an empty file descriptor set by make method:

(make <sys-fdset>)
Function: sys-fdset elt …

Creates a new <sys-fdset> instance with file descriptors specified by elt …. Each elt can be an integer file descriptor, a port, or a <sys-fdset> instance. In the last case, the descriptors in the given fdset is copied to the new fdset.

Function: sys-fdset-ref fdset port-or-fd
Function: sys-fdset-set! fdset port-or-fd flag

Gets and sets specific file descriptor bit of fdset. port-or-fd may be a port or an integer file descriptor. If port-or-fd is a port that doesn’t have associated file descriptor, sys-fdset-ref returns #f, and sys-fdset-set! doesn’t modify fdset. flag must be a boolean value.

You can use generic setter of sys-fdset-ref as this:

(set! (sys-fdset-ref fdset port-or-fd) flag)
  ≡ (sys-fdset-set! fdset port-or-fd flag)
Function: sys-fdset-copy! dest-fdset src-fdset

Copies the content of src-fdset into dest-fdset. Returns dest-fdset.

Function: sys-fdset-clear! fdset

Empties and returns fdset.

Function: sys-fdset->list fdset
Function: list->sys-fdset fds

Converts an fdset to a list of integer file descriptors and vice versa. In fact, list->sys-fdset works just like (lambda (fds) (apply sys-fdset fds)), so it accepts ports and other fdsets as well as integer file descriptors.

Function: sys-fdset-max-fd fdset

Returns the maximum file descriptor number in fdset.

Function: sys-select readfds writefds exceptfds :optional timeout
Function: sys-select! readfds writefds exceptfds :optional timeout

Waits for a set of file descriptors to change status. readfds, writefds, and exceptfds are <fdset> objects to represent a set of file descriptors to watch. File descriptors in readfds are watched to see if characters are ready to be read. File descriptors in writefds are watched if writing to them is ok. File descriptors in exceptfds are watched for exceptions. You can pass #f to one or more of those arguments if you don’t care about watching the condition.

timeout specifies maximum time sys-select waits for the condition change. It can be a real number, for number of microseconds, or a list of two integers, the first is the number of seconds and the second is the number of microseconds. If you pass #f, sys-select waits indefinitely.

sys-select returns four values. The first value is a number of descriptors it detected status change. It may be zero if timeout expired. The second, third and fourth values are <fdset> object that contains a set of descriptors that changed status for reading, writing, and exception, respectively. If you passed #f to one or more of readfds, writefds and exceptfds, the corresponding return value is #f.

sys-select! variant works the same as sys-select, except it modifies the passed <fdset> arguments. sys-select creates new <fdset> objects and doesn’t modify its arguments.


6.24.12 Garbage collection

The garbage collector runs implicitly whenever it is necessary, and you don’t usually need to worry about it. However, in case if you do need to worry, here are a few procedures you can use.

Function: gc

Trigger a full GC. It may be useful if you want to reduce interference of GC in certain parts of code by calling this immediately before that.

Function: gc-stat

Returns a list of lists, each inner list contains a keyword and related statistics. Current statistics include :total-heap-size, :free-bytes, :bytes-since-gc and :total-bytes.


6.24.13 Memory mapping

Class: <memory-region>

An object representing a mapped memory pages. It is returned from sys-mmap, and can be passed to make-view-uvector to access. It has the following read-only slots.

Instance Variable of <memory-region>: address

The address of the mapping. Not useful in the Scheme world, but you may need to pass this to foreign functions.

Instance Variable of <memory-region>: size

The size of the mapping, in bytes.

Instance Variable of <memory-region>: protection

The bitmask represents memory protection. It is a bitwise OR of integer constants PROT_READ, PROT_WRITE, PROT_EXEC and PROT_NONE. See sys-mmap below for thedetails.

Instance Variable of <memory-region>: flags

the flags passed to the sys-mmap. See sys-mmap below for the details.

Function: sys-mmap port prot flags size :optional offset

[POSIX] Maps files into memory using mmap(2) (or MapViewOfFileEx on Windows). Returns a <memory-region> object, which can be accessed via make-view-uvector.

The port argument must be either a port or #f. If it is a port, it must have underlying file. If it is #f, the mapping becomes “anonymous” (not backed with a file); in that case, MAP_ANONYMOUS flag must also be specified in flags.

The prot argument specifies the protection bits of the memory region; it must be an integer created by bitwise-OR of the following constants:

PROT_EXEC

The mapped pages may be executed.

PROT_READ

The mapped pages may be read.

PROT_WRITE

The mapped pages may be written.

PROT_NONE

Pages may not be accessed.

The flags argument must be an integer created by bitwise-OR of the following constants:

MAP_SHARED

The mapping is shared among processes. If you update the mapped pages, other processes mapping the same region can see it, too.

MAP_PRIVATE

The mapping is private to this process. If you update the mapped pages, it stays in the process and is not visible from outside.

MAP_ANONYMOUS

The pages don’t have a backing file.

The size argument must be a positive exact integer, and the offset argument must be a non-negative exact integer. They specify the region of the file to be mapped; size bytes starting from offset bytes. The offset must be a multiple of the page size. If offfset is omitted, 0 is assumed. If you’re mapping non-file-backed memory (when port is #f), offset is ignored.

You don’t need to unmap the mapped pages explicitly; when the created <memory-region> object is garbage collected, the memory is unmapped.

Function: make-view-uvector mem class length :optional offset immutable?

This procedure creates a uniform vector that works as a “window” to the memory region mem, which must be a <memory-region> object. If the underlying memory content changes, it is visible through the uvector. If the memory region is writeble and you mutate the uvector, it is reflected to the underlying memory region.

The class argument must be one of the uniform vector class (e.g. <u8vector>), and length is the length of the uvector to be created. The length is the number of elements, not the number of bytes. The memory is accessed with the native endianness. Length can be #f, in that case up to the end of the memory region is used.

The offset argument specifies the offset from the beginning of memory region, in number of bytes. It must be a multiple of the uvector’s element size.

If the memory region is read-only (i.e. it is mapped without PROT_WRITE), the resulting uvector is immutable. Otherwise, it is mutable by default, but ynou can give a true value to immutable? argument to create an immutable uvector.

The memory region isn’t garbage collected as long as there’re uvectors that referencing the region.


6.24.14 Miscellaneous system calls

Function: sys-pause

[POSIX] Suspends the process until it receives a signal whose action is to either execute a signal-catching function or to terminate the process. This function only returns when the signal-catching function returns. The returned value is undefined.

Note that just calling pause() doesn’t suffice the above semantics in Scheme-level. Internally this procedure calls sigsuspend() with the current signal mask.

Function: sys-alarm seconds

[POSIX] Arranges a SIGALRM signal to be delivered after seconds. The previous settings of the alarm clock is canceled. Passing zero to seconds doesn’t schedule new alarm. Returns the number of seconds remaining until previously scheduled alarm was due to be delivered (or zero if no alarm is active).

Function: sys-sleep seconds :optional (no-retry #f)

[POSIX] Suspends the calling thread until the specified number of seconds elapses.

Note that libc’s sleep(3) could return before the specified interval if the calling thread receives a signal; in that case, sys-sleep automatically restarts sleep(3) again with remaining time interval (after invoking Scheme signal handlers if there’s any) by default. So you can count on the thread does sleep at least the specified amount of time.

If you do want sys-sleep to return prematurely upon receiving a signal, you can give a true value to an optional argument no-retry.

The reason that we retries by default is that Gauche’s GC may use signals to synchronize between threads. If GC is invoked by one thread While another thread is sleeping on sleep(3), it may return prematurely. It could happen often if other threads allocate a lot, which could make sys-sleep unreliable.

Returns zero if it sleeps well (which is always the case if no-retry is false), or the number of unslept seconds if it is woke up by a signal.

To be portable across POSIX implementation, keep seconds less than 65536.

Some systems may be using alarm(2) to implement sleep(3), so you shouldn’t mix sys-sleep and sys-alarm.

Function: sys-nanosleep nanoseconds :optional (no-retry #f)

[POSIX] Suspends the calling thread until the specified number of nanoseconds elapses. The argument nanoseconds can be a <time> object (see Time), or a real number.

The system’s nanosleep(2) could return before the specified interval if the calling thread receives a signal; in that case, sys-nanosleep automatically restarts nanosleep(2) again with remaining time interval (after invoking Scheme signal handlers if there’s any) by default. So you can count on the thread does sleep at least the specified amount of time.

The reason that we retries by default is that Gauche’s GC may use signals to synchronize between threads. If GC is invoked by one thread while another thread is sleeping on nanosleep(2), it may return prematurely. It could happen often if other threads allocate a lot, which could make sys-nanosleep unreliable.

Returns #f if nanoseconds elapsed (which is always the case if no-retry is #f), or a <time> object that indicates the remaining time if sys-nanosleep is interrupted by a signal.

;wait for 0.5 sec
(sys-nanosleep 500000000)

;wait for 1.3 sec
(sys-nanosleep (make <time> :second 1 :nanosecond 300000000))

Note: On Windows native platforms, this function is emulated using Sleep. The argument is rounded up to millisecond resolution, and it won’t be interrupted by a signal.

Function: sys-random
Function: sys-srandom seed

A pseudo random number generator. sys-random returns a random number between 0 and a positive integer rand_max, inclusive. This is a straightforward interface to random(3). If the underlying system doesn’t have random(3), lrand48(3) is used.

sys-srandom sets the seed of the random number generator. It uses either srandom(3) or srand48(3), depending on the system.

The intention of these functions are to provide an off-the-stock handy random number generator (RNG) for applications that doesn’t sensitive to the quality and/or speed of RNG. For serious statistics analysis, use Mersenne Twister RNG in math.mt-random module (see math.mt-random - Mersenne Twister Random number generator).

Variable: RAND_MAX

Bound to a positive integer that sys-random may return.

Function: sys-get-osfhandle port-or-fd

[Windows] This procedure is only available on Windows native platforms. Returns a Windows file handle associated to the given port or integer file descriptor. Throws an error if the given argument does not have associated file handle.



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT