commit 8ba811fb48d666a23d60a5ce3a947dcac7baf6ea
parent ab2813a10a7fe6edbbef2acdfd22c0666171f566
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Sat, 9 Sep 2023 14:10:40 +0000
Document cspawn
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat:
6 files changed, 140 insertions(+), 48 deletions(-)
diff --git a/NEWS b/NEWS
@@ -1,6 +1,6 @@
Changelog for skalibs.
-In 2.13.2.0
+In 2.14.0.0
-----------
- Bugfixes.
diff --git a/doc/crosscompile.html b/doc/crosscompile.html
@@ -83,13 +83,17 @@ the time <tt>yes</tt> or <tt>no</tt>.
<p>
At all times, <tt>./configure --help</tt> provides the list of sysdeps
you need to provide a <tt>--with-sysdep-*</tt> option for. As of
-skalibs-2.9.3.0, there is only one sysdep in this case:
+skalibs-2.14.0.0, there are two sysdeps in this case:
</p>
<ul>
<li> <tt>devurandom</tt>: <tt>yes</tt> if the target has a valid
pseudorandom generation device in <tt>/dev/urandom</tt>, and <tt>no</tt>
otherwise. </li>
+ <li> <tt>posixspawnearlyreturn</tt>: <tt>yes</tt> if the target has a broken
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html">posix_spawn()</a>
+implementation that can return before the child has successfully exec'ed.
+That happens with old glibcs and some virtual platforms. </li>
</ul>
</body>
diff --git a/doc/libstddjb/cspawn.html b/doc/libstddjb/cspawn.html
@@ -0,0 +1,130 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>skalibs: the cspawn library interface</title>
+ <meta name="Description" content="skalibs: the cspawn library interface" />
+ <meta name="Keywords" content="skalibs c unix cspawn fork posix_spawn child process exec library libstddjb" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">libstddjb</a><br />
+<a href="../libskarnet.html">libskarnet</a><br />
+<a href="../index.html">skalibs</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>cspawn</tt> library interface </h1>
+
+<p>
+ The following functions are declared in the <tt>skalibs/cspawn.h</tt> header,
+and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library.
+</p>
+
+<h2> General information </h2>
+
+<p>
+ <tt>cspawn</tt> is a unifier API to spawn child processes with
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html">posix_spawn()</a>
+as a backend if supported by the system, falling back on
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html">fork()</a> +
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html">execve()</a>
+otherwise.
+</p>
+
+<h2> Functions </h2>
+
+<h3> Primitive </h3>
+
+<p>
+<code> pid_t cspawn (char const *file, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) </code> <br />
+Forks and execs a child as with <tt>exec_ae(file, argv, envp)</tt>.
+Returns 0 if it fails, and the pid of the child if it succeeds.
+Before execing, the following operations are performed in the child:
+</p>
+
+<ul>
+ <li> If <em>flags</em> contains (the or-able value) CSPAWN_FLAGS_SIGBLOCKNONE,
+the child's signal processing mask is reset - no signal will be blocked. </li>
+ <li> Alternatively, if <em>flags</em> contains (the or-able value) CSPAWN_FLAGS_SELFPIPE_FINISH,
+the child's signal state is reset to what it was before the invocation of
+<tt>selfpipe_init()</tt> in the parent. </li>
+ <li> The file actions described in the array <em>fa</em>, which must have at least <em>n</em> elements,
+are processed in order. For every <em>i</em> from 0 to <em>n</em>-1:
+ <ul>
+ <li> if <tt>fa[i].type</tt> is CSPAWN_FA_CLOSE, then file descriptor <tt>fa[i].x.fd</tt> is closed </li>
+ <li> else if <tt>fa[i].type</tt> is CSPAWN_FA_MOVE, then file descriptor <tt>fa[i].x.fd2[1]</tt>
+is moved to <tt>fa[i].x.fd2[0]</tt> </li>
+ <li> else if <tt>fa[i].type</tt> is CSPAWN_FA_COPY, then file descriptor <tt>fa[i].x.fd2[1]</tt>
+is copied to <tt>fa[i].x.fd2[0]</tt>, as with <tt>dup2(fa[i].x.fd2[1], fa[i].x.fd2[0])</tt> </li>
+ <li> else if <tt>fa[i].type</tt> is CSPAWN_FA_OPEN, then file <tt>fa[i].x.openinfo.file</tt> is
+opened with flags <tt>fa[i].x.openinfo.oflag</tt> and mode <tt>fa[i].x.openinfo.mode</tt>, and file
+descriptor <tt>fa[i].x.openinfo.fd</tt> points to it. </li>
+ </ul> </li>
+</ul>
+
+<h3> Higher level interfaces </h3>
+
+<p>
+<code> pid_t child_spawn1_pipe (char const *file, char const *const *argv, char const *const *envp, int *fd, int w) </code> <br />
+Spawns <em>file</em> as with <tt>cspawn()</tt> with a <em>flags</em> value of CSPAWN_FLAGS_SIGBLOCKNONE;
+a pipe is created between the child's
+stdin (if <em>w</em> is 0) or stdout (if <em>w</em> is nonzero) and the parent.
+The parent's end of the pipe will be stored in *<em>fd</em>.
+</p>
+
+<p>
+<code> pid_t child_spawn1_socket (char const *file, char const *const *argv, char const *const *envp, int *fd) </code> <br />
+Like <tt>child_spawn1</tt>, except that a socket, not a pipe is created between the parent
+and the child. Both the child's stdin and stdout point to the socket; the parent has
+its end of the socket available in *<em>fd</em>.
+</p>
+
+<p>
+<code> pid_t child_spawn2 (char const *file, char const *const *argv, char const *const *envp, int *fds) </code> <br />
+Two pipes are created between the
+parent and the child. <em>fds</em> must point to an array of 2 ints: this
+array is read as well as written by <tt>child_spawn2()</tt>. On function
+call, the numbers in <em>fds</em> must describe what fds should be used
+in the child to contain the communication pipes (for instance, if the child
+will read from its parent on stdin and write to its parent on stdout, <em>fds</em>
+must contain 0 and 1). On function return, <em>fds</em> contains the
+descriptors for the pipes that read from / write to the child.
+</p>
+
+<p>
+<code> pid_t child_spawn3 (char const *file, char const *const *argv, char const *const *envp, int *fds) </code> <br />
+Three pipes are created between the
+parent and the child. <em>fds</em> must point to an array of 3 ints: this
+array is read as well as written by <tt>child_spawn2()</tt>. On function
+call, the numbers in <em>fds[0]</em> and <em>fds[1]</em> must describe what fds should be used
+in the child to read from (resp. write to) the parent.
+On function return, <em>fds</em> contains the
+descriptors for the pipes that read from / write to the child. <em>fds[2]</em> is
+the reading end of a pipe; the writing end is present in the child, and its number
+is available as the value of the <tt>SKALIBS_CHILD_SPAWN_FDS</tt> environment variable.
+</p>
+
+
+<p>
+<code> pid_t child_spawn (char const *file, char const *const *argv, char const *const *envp, int *fds, unsigned int nfds) </code> <br />
+More generic spawning function. <em>fds</em> must point to an array of at least <em>nfds</em> ints;
+file descriptors reading from or writing to the child will be stored there. The function returns
+0 on failure or the pid of the child on success.
+</p>
+<ul>
+ <li> If <em>nfds</em> is 0, then the function behaves like <tt>cspawn</tt> with a flags value
+of CSPAWN_FLAGS_SIGBLOCKNONE. </li>
+ <li> If <em>nfds</em> is 1 or more, then <em>fds</em> will contain pipes between the
+child and the parent. The parent will read on even-numbered ones
+and write on odd-numbered ones. The child will read on <em>fds[0]</em>, write on <em>fds[1]</em>,
+then any additional fds are available to it in the <tt>SKALIBS_CHILD_SPAWN_FDS</tt> environment
+variable as a comma-separated list of integers. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/libstddjb/djbunix.html b/doc/libstddjb/djbunix.html
@@ -357,53 +357,10 @@ and the grandchild's PID if the current process is the parent.
</p>
<p>
-<code> pid_t child_spawn0 (char const *file, char const *const *argv, char const *const *envp) </code> <br />
-Forks and executes a child as with <tt>exec_ae(file, argv, envp)</tt>.
-Returns 0 if it fails, and the pid of the child if it succeeds.
-Implemented via <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html">posix_spawn()</a>
-on systems that support it.
+The <tt>child_spawn</tt> family of functions has been moved to the
+<a href="cspawn.html">skalibs/cspawn.h</a> header.
</p>
-<p>
-<code> pid_t child_spawn1_pipe (char const *file, char const *const *argv, char const *const *envp, int *fd, int w) </code> <br />
-Like <tt>child_spawn0()</tt>, except that a pipe is created between the child's
-stdin (if <em>w</em> is 0) or stdout (if <em>w</em> is nonzero) and the parent.
-The parent's end of the pipe will be stored in *<em>fd</em>.
-</p>
-
-<p>
-<code> pid_t child_spawn1_socket (char const *file, char const *const *argv, char const *const *envp, int *fd) </code> <br />
-Like <tt>child_spawn0</tt>, except that a socket is created between the parent
-and the child. Both the child's stdin and stdout point to the socket; the parent has
-its end of the socket available in *<em>fd</em>.
-</p>
-
-<p>
-<code> pid_t child_spawn2 (char const *file, char const *const *argv, char const *const *envp, int *fds) </code> <br />
-Like <tt>child_spawn0()</tt>, except that two pipes are created between the
-parent and the child. <em>fds</em> must point to an array of 2 ints: this
-array is read as well as written by <tt>child_spawn2()</tt>. On function
-call, the numbers in <em>fds</em> must describe what fds should be used
-in the child to contain the communication pipes (for instance, if the child
-will read from its parent on stdin and writes to its parent on stdout, <em>fds</em>
-must contain 0 and 1). On function return, <em>fds</em> contains the
-descriptors for the pipes that read from / write to the child.
-</p>
-
-<p>
-<code> pid_t child_spawn (char const *file, char const *const *argv, char const *const *envp, int *fds, unsigned int nfds) </code> <br />
-More generic spawning function. <em>fds</em> must point to an array of at least <em>nfds</em> ints;
-file descriptors reading from or writing to the child will be stored there. The function returns
-0 on failure or the pid of the child on success.
-</p>
-<ul>
- <li> If <em>nfds</em> is 0, then the function behaves like <tt>child_spawn0</tt>, except
-all ignored signals will be un-ignored in the child </li>
- <li> If <em>nfds</em> is 1 or more, then <em>fds</em> will contain pipes between the
-child and the parent. The parent will read on even-numbered ones (starting on <em>fds</em>[0])
-and write on odd-numbered ones. </li>
-</ul>
-
<h3> Waiting for children </h3>
<p>
diff --git a/doc/libstddjb/index.html b/doc/libstddjb/index.html
@@ -57,6 +57,7 @@ wrappers</a> around I/O functions, extra I/O functions </li>
<a href="https://en.wikipedia.org/wiki/Cdb_%28software%29">cdb</a> files </li>
<li> <a href="cdbmake.html">skalibs/cdbmake.h</a>: how to write
<a href="https://en.wikipedia.org/wiki/Cdb_%28software%29">cdb</a> files </li>
+ <li> <a href="cspawn.html">skalibs/cspawn.h</a>: child spawning primitives that use posix_spawn instead of fork when supported </li>
<li> <a href="direntry.html">skalibs/direntry.h</a>: portable directory operations </li>
<li> <a href="djbtime.html">skalibs/djbtime.h</a>: conversions between date and time formats </li>
<li> <a href="djbunix.html">skalibs/djbunix.h</a>: management of basic Unix concepts </li>
diff --git a/doc/license.html b/doc/license.html
@@ -74,7 +74,7 @@ color, or different text font. </li>
<p>
<em>I am aware that the previous restrictions sound completely
ridiculous while the official skalibs documentation is incomplete.
-As of 2.13.1.1, I'm not going to enforce those restrictions, but if you're
+As of 2.14.0.0, I'm not going to enforce those restrictions, but if you're
going to provide documentation for skalibs, don't keep it to yourself,
please send it to me instead. :-) </em>
</p>