skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

commit 5f76ed9108c5c48850cf339096527c4d53f0bc12
parent b19b3e0682d6e224c12b35308772114fe27372fe
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Thu, 18 Dec 2014 19:06:06 +0000

 Separate socket from pipe in child_spawn. Less code in skaclient!

Diffstat:
Mpackage/deps.mak | 7+++++--
Msrc/include/skalibs/djbunix.h | 8++++----
Msrc/libstddjb/child_spawn.c | 73+++++++++++++++++++++----------------------------------------------------
Dsrc/libstddjb/child_spawn1.c | 115-------------------------------------------------------------------------------
Asrc/libstddjb/child_spawn1_internal.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libstddjb/child_spawn1_pipe.c | 16++++++++++++++++
Asrc/libstddjb/child_spawn1_socket.c | 16++++++++++++++++
Asrc/libstddjb/djbunix-internal.h | 10++++++++++
Msrc/libunixonacid/skaclient_startf_async.c | 2+-
9 files changed, 198 insertions(+), 174 deletions(-)

diff --git a/package/deps.mak b/package/deps.mak @@ -49,6 +49,7 @@ src/include/skalibs/strerr.h: src/include/skalibs/gccattributes.h src/include/skalibs/strerr2.h: src/include/skalibs/strerr.h src/include/skalibs/surf.h: src/include/skalibs/uint32.h src/include/skalibs/tai.h: src/include/skalibs/gccattributes.h src/include/skalibs/uint32.h src/include/skalibs/uint64.h +src/include/skalibs/uint32.h: src/include/skalibs/uint64.h src/include/skalibs/unirandom.h: src/include/skalibs/buffer.h src/include/skalibs/surf.h src/include/skalibs/unirandomdev.h: src/include/skalibs/unirandom.h src/include/skalibs/unirandomegd.h: src/include/skalibs/unirandom.h @@ -274,9 +275,11 @@ src/libstddjb/cdb_nextkey.o src/libstddjb/cdb_nextkey.lo: src/libstddjb/cdb_next src/libstddjb/cdb_read.o src/libstddjb/cdb_read.lo: src/libstddjb/cdb_read.c src/include/skalibs/allreadwrite.h src/include/skalibs/bytestr.h src/include/skalibs/cdb.h src/include/skalibs/djbunix.h src/include/skalibs/error.h src/include/skalibs/uint32.h src/libstddjb/cdb_successor.o src/libstddjb/cdb_successor.lo: src/libstddjb/cdb_successor.c src/include/skalibs/cdb.h src/include/skalibs/uint32.h src/libstddjb/cdb_zero.o src/libstddjb/cdb_zero.lo: src/libstddjb/cdb_zero.c src/include/skalibs/cdb.h -src/libstddjb/child_spawn.o src/libstddjb/child_spawn.lo: src/libstddjb/child_spawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/bytestr.h src/include/skalibs/config.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/sig.h src/include/skalibs/strerr2.h src/include/skalibs/sysdeps.h src/include/skalibs/uint.h src/include/skalibs/webipc.h +src/libstddjb/child_spawn.o src/libstddjb/child_spawn.lo: src/libstddjb/child_spawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/bytestr.h src/include/skalibs/config.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/sig.h src/include/skalibs/strerr2.h src/include/skalibs/sysdeps.h src/include/skalibs/uint.h src/libstddjb/child_spawn0.o src/libstddjb/child_spawn0.lo: src/libstddjb/child_spawn0.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/sysdeps.h -src/libstddjb/child_spawn1.o src/libstddjb/child_spawn1.lo: src/libstddjb/child_spawn1.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/sysdeps.h +src/libstddjb/child_spawn1_internal.o src/libstddjb/child_spawn1_internal.lo: src/libstddjb/child_spawn1_internal.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/sig.h src/include/skalibs/sysdeps.h +src/libstddjb/child_spawn1_pipe.o src/libstddjb/child_spawn1_pipe.lo: src/libstddjb/child_spawn1_pipe.c src/libstddjb/djbunix-internal.h src/include/skalibs/djbunix.h +src/libstddjb/child_spawn1_socket.o src/libstddjb/child_spawn1_socket.lo: src/libstddjb/child_spawn1_socket.c src/libstddjb/djbunix-internal.h src/include/skalibs/djbunix.h src/include/skalibs/webipc.h src/libstddjb/coe.o src/libstddjb/coe.lo: src/libstddjb/coe.c src/include/skalibs/djbunix.h src/libstddjb/deepsleepuntil.o src/libstddjb/deepsleepuntil.lo: src/libstddjb/deepsleepuntil.c src/include/skalibs/iopause.h src/include/skalibs/tai.h src/libstddjb/dir_close.o src/libstddjb/dir_close.lo: src/libstddjb/dir_close.c src/include/skalibs/direntry.h diff --git a/src/include/skalibs/djbunix.h b/src/include/skalibs/djbunix.h @@ -129,18 +129,18 @@ extern int rmstar (char const *) ; extern int rmstar_tmp (char const *, stralloc *) ; - /* Simple spawn functions. 0 for no communication, 1 for a child/parent pipe. */ + /* Simple spawn functions with 0 or 1 communicating fds. */ extern pid_t child_spawn0 (char const *, char const *const *, char const *const *) ; -extern pid_t child_spawn1 (char const *, char const *const *, char const *const *, int *, int) ; +extern pid_t child_spawn1_pipe (char const *, char const *const *, char const *const *, int *, int) ; +extern pid_t child_spawn1_socket (char const *, char const *const *, char const *const *, int *) ; /* Unified function to fork a child with communication canals. * uses posix_spawn() if available, else uses fork+exec * requests n (the last arg) communication fds between parent and child - * if n=1, the fd is a Unix socket. If more canals are needed, you can - pass them through that socket. + * if n=1, equivalent to child_spawn1_pipe; child writes, parent reads. * if n>=2, the fds are pipes, parent reads on even and writes on odd. */ diff --git a/src/libstddjb/child_spawn.c b/src/libstddjb/child_spawn.c @@ -15,7 +15,6 @@ #include <skalibs/env.h> #include <skalibs/djbunix.h> #include <skalibs/uint.h> -#include <skalibs/webipc.h> #ifdef SKALIBS_HASPOSIXSPAWN @@ -35,9 +34,7 @@ /* If n = 0 : child's stdin and stdout are the same as the parent's - If n = 1 : Unix socket between parent and child. - Additional canals, if needed, may be fd-passed through it. - If n >= 2 : pipes between parent and child. + If n >= 1 : pipes between parent and child. Parent reads on even ones, writes on odd ones. */ @@ -53,17 +50,10 @@ pid_t child_spawn (char const *prog, char const *const *argv, char const *const pid_t pid ; int e ; unsigned int m = sizeof(NOFDVAR) ; - unsigned int i ; + unsigned int i = 0 ; char modifs[m + 1 + n * UINT_FMT] ; byte_copy(modifs, sizeof(NOFDVAR), NOFDVAR "=") ; - if (n == 1) - { - if (ipc_pair_b(p[0]) < 0) return 0 ; - } - else if (n >= 2) - { - for (i = 0 ; i < n ; i++) if (pipe(p[i]) < 0) { e = errno ; goto errp ; } - } + for (; i < n ; i++) if (pipe(p[i]) < 0) { e = errno ; goto errp ; } for (i = 0 ; i < n ; i++) if ((ndelay_on(p[i][i & 1]) < 0) || (coe(p[i][i & 1]) < 0)) { @@ -88,28 +78,19 @@ pid_t child_spawn (char const *prog, char const *const *argv, char const *const if (e) goto errattr ; e = posix_spawn_file_actions_init(&actions) ; if (e) goto errattr ; - switch (n) + if (n >= 2) + { + e = posix_spawn_file_actions_adddup2(&actions, p[1][0], 0) ; + if (e) goto erractions ; + e = posix_spawn_file_actions_addclose(&actions, p[1][0]) ; + if (e) goto erractions ; + } + if (n) { - case 0 : - break ; - case 1 : - e = posix_spawn_file_actions_adddup2(&actions, p[0][1], 1) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_addclose(&actions, p[0][1]) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_adddup2(&actions, 1, 0) ; - if (e) goto erractions ; - break ; - default : - e = posix_spawn_file_actions_adddup2(&actions, p[1][0], 0) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_addclose(&actions, p[1][0]) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_adddup2(&actions, p[0][1], 1) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_addclose(&actions, p[0][1]) ; - if (e) goto erractions ; - break ; + e = posix_spawn_file_actions_adddup2(&actions, p[0][1], 1) ; + if (e) goto erractions ; + e = posix_spawn_file_actions_addclose(&actions, p[0][1]) ; + if (e) goto erractions ; } { int haspath = !!env_get("PATH") ; @@ -142,25 +123,13 @@ pid_t child_spawn (char const *prog, char const *const *argv, char const *const byte_copy(name + len, 9, " (child)") ; PROG = name ; fd_close(syncpipe[0]) ; - switch (n) + if (n >= 2) { - case 0 : - { - int fd = open2("/dev/null", O_RDONLY) ; - if (fd < 0) goto syncdie ; - if (fd_move(0, fd) < 0) goto syncdie ; - fd = open2("/dev/null", O_WRONLY) ; - if (fd < 0) goto syncdie ; - if (fd_move(1, fd) < 0) goto syncdie ; - break ; - } - case 1 : - if (fd_move(1, p[0][1]) < 0) goto syncdie ; - if (fd_copy(0, 1) < 0) goto syncdie ; - break ; - default : - if (fd_move2(0, p[1][0], 1, p[0][1]) < 0) goto syncdie ; - break ; + if (fd_move2(0, p[1][0], 1, p[0][1]) < 0) goto syncdie ; + } + else if (n) + { + if (fd_move(1, p[0][1]) < 0) goto syncdie ; } sig_blocknone() ; pathexec_r_name(prog, argv, envp, env_len(envp), modifs, m) ; diff --git a/src/libstddjb/child_spawn1.c b/src/libstddjb/child_spawn1.c @@ -1,115 +0,0 @@ -/* ISC license. */ - -#include <skalibs/sysdeps.h> -#include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#include <skalibs/djbunix.h> - -#ifdef SKALIBS_HASPOSIXSPAWN - -#include <spawn.h> -#include <stdlib.h> -#include <skalibs/config.h> -#include <skalibs/env.h> - -pid_t child_spawn1 (char const *prog, char const *const *argv, char const *const *envp, int *fd, int to) -{ - posix_spawn_file_actions_t actions ; - int e ; - int p[2] ; - pid_t pid ; - int haspath = !!env_get("PATH") ; - if (pipe(p) < 0) return 0 ; - to = !!to ; - e = posix_spawn_file_actions_init(&actions) ; - if (e) goto err ; - e = posix_spawn_file_actions_addclose(&actions, p[!to]) ; - if (e) goto erractions ; - e = posix_spawn_file_actions_adddup2(&actions, p[to], to) ; - if (e) goto erractions ; - if (!haspath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; } - e = posix_spawnp(&pid, prog, &actions, 0, (char *const *)argv, (char *const *)envp) ; - if (!haspath) unsetenv("PATH") ; - posix_spawn_file_actions_destroy(&actions) ; - fd_close(p[to]) ; - if (e) goto errp ; - *fd = p[!to] ; - return pid ; - - erractions: - posix_spawn_file_actions_destroy(&actions) ; - err: - fd_close(p[to]) ; - errp: - fd_close(p[!to]) ; - errno = e ; - return 0 ; -} - -#else - -#include <skalibs/allreadwrite.h> - -pid_t child_spawn1 (char const *prog, char const *const *argv, char const *const *envp, int *fd, int to) -{ - int e ; - int syncp[2] ; - int p[2] ; - pid_t pid ; - if (pipe(p) < 0) return 0 ; - if (pipecoe(syncp) < 0) - { - e = errno ; - fd_close(p[1]) ; - fd_close(p[0]) ; - errno = e ; - return 0 ; - } - to = !!to ; - pid = fork() ; - if (pid < 0) - { - e = errno ; - fd_close(syncp[1]) ; - fd_close(syncp[0]) ; - fd_close(p[1]) ; - fd_close(p[0]) ; - errno = e ; - return 0 ; - } - if (pid) - { - fd_close(syncp[0]) ; - fd_close(p[!to]) ; - if (fd_move(to, p[to]) < 0) goto err ; - pathexec_run(prog, argv, envp) ; -err: - e = errno ; - fd_write(syncp[1], (char *)&e, sizeof(e)) ; - _exit(127) ; - } - fd_close(syncp[1]) ; - fd_close(p[to]) ; - syncp[1] = fd_read(syncp[0], (char *)&e, sizeof(e)) ; - if (syncp[1] < 0) - { - e = errno ; - fd_close(syncp[0]) ; - fd_close(p[!to]) ; - errno = e ; - return 0 ; - } - fd_close(syncp[0]) ; - if (syncp[1] == sizeof(e)) - { - fd_close(p[!to]) ; - wait_pid(pid, &syncp[1]) ; - errno = e ; - return 0 ; - } - *fd = p[!to] ; - return pid ; -} - -#endif diff --git a/src/libstddjb/child_spawn1_internal.c b/src/libstddjb/child_spawn1_internal.c @@ -0,0 +1,125 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <skalibs/djbunix.h> + +#ifdef SKALIBS_HASPOSIXSPAWN + +#include <signal.h> +#include <spawn.h> +#include <stdlib.h> +#include <skalibs/config.h> +#include <skalibs/env.h> + +pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to) +{ + posix_spawn_file_actions_t actions ; + posix_spawnattr_t attr ; + int e ; + pid_t pid ; + int haspath = !!env_get("PATH") ; + to = !!to ; + if (coe(p[!to]) < 0) { e = errno ; goto err ; } + e = posix_spawnattr_init(&attr) ; + if (e) goto err ; + { + sigset_t set ; + sigemptyset(&set) ; + e = posix_spawnattr_setsigmask(&attr, &set) ; + } + if (e) goto errattr ; + e = posix_spawn_file_actions_init(&actions) ; + if (e) goto errattr ; + e = posix_spawn_file_actions_addclose(&actions, p[!to]) ; + if (e) goto erractions ; + e = posix_spawn_file_actions_adddup2(&actions, p[to], to) ; + if (e) goto erractions ; + if (!haspath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; } + e = posix_spawnp(&pid, prog, &actions, &attr, (char *const *)argv, (char *const *)envp) ; + if (!haspath) unsetenv("PATH") ; + posix_spawn_file_actions_destroy(&actions) ; + posix_spawnattr_destroy(&attr) ; + fd_close(p[to]) ; + if (e) goto errp ; + return pid ; + + erractions: + posix_spawn_file_actions_destroy(&actions) ; + errattr: + posix_spawnattr_destroy(&attr) ; + err: + fd_close(p[to]) ; + errp: + fd_close(p[!to]) ; + errno = e ; + return 0 ; +} + +#else + +#include <skalibs/allreadwrite.h> +#include <skalibs/sig.h> + +pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to) +{ + int e ; + int syncp[2] ; + pid_t pid ; + if (coe(p[0]) < 0 || pipecoe(syncp) < 0) + { + e = errno ; + fd_close(p[1]) ; + fd_close(p[0]) ; + errno = e ; + return 0 ; + } + to = !!to ; + pid = fork() ; + if (pid < 0) + { + e = errno ; + fd_close(syncp[1]) ; + fd_close(syncp[0]) ; + fd_close(p[1]) ; + fd_close(p[0]) ; + errno = e ; + return 0 ; + } + if (pid) + { + fd_close(syncp[0]) ; + fd_close(p[!to]) ; + if (fd_move(to, p[to]) < 0) goto err ; + sig_blocknone() ; + pathexec_run(prog, argv, envp) ; +err: + e = errno ; + fd_write(syncp[1], (char *)&e, sizeof(e)) ; + _exit(127) ; + } + fd_close(syncp[1]) ; + fd_close(p[to]) ; + syncp[1] = fd_read(syncp[0], (char *)&e, sizeof(e)) ; + if (syncp[1] < 0) + { + e = errno ; + fd_close(syncp[0]) ; + fd_close(p[!to]) ; + errno = e ; + return 0 ; + } + fd_close(syncp[0]) ; + if (syncp[1] == sizeof(e)) + { + fd_close(p[!to]) ; + wait_pid(pid, &syncp[1]) ; + errno = e ; + return 0 ; + } + return pid ; +} + +#endif diff --git a/src/libstddjb/child_spawn1_pipe.c b/src/libstddjb/child_spawn1_pipe.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <unistd.h> +#include <skalibs/djbunix.h> +#include "djbunix-internal.h" + +pid_t child_spawn1_pipe (char const *prog, char const *const *argv, char const *const *envp, int *fd, int to) +{ + pid_t pid ; + int p[2] ; + if (pipe(p) < 0) return 0 ; + pid = child_spawn1_internal(prog, argv, envp, p, !!to) ; + if (!pid) return 0 ; + *fd = p[!to] ; + return pid ; +} diff --git a/src/libstddjb/child_spawn1_socket.c b/src/libstddjb/child_spawn1_socket.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/webipc.h> +#include <skalibs/djbunix.h> +#include "djbunix-internal.h" + +pid_t child_spawn1_socket (char const *prog, char const *const *argv, char const *const *envp, int *fd) +{ + pid_t pid ; + int p[2] ; + if (ipc_pair_b(p) < 0) return 0 ; + pid = child_spawn1_internal(prog, argv, envp, p, 1) ; + if (!pid) return 0 ; + *fd = p[0] ; + return pid ; +} diff --git a/src/libstddjb/djbunix-internal.h b/src/libstddjb/djbunix-internal.h @@ -0,0 +1,10 @@ +/* ISC license. */ + +#ifndef DJBUNIX_INTERNAL_H +#define DJBUNIX_INTERNAL_H + +#include <sys/types.h> + +extern pid_t child_spawn1_internal (char const *, char const *const *, char const *const *, int *, int) ; + +#endif diff --git a/src/libunixonacid/skaclient_startf_async.c b/src/libunixonacid/skaclient_startf_async.c @@ -32,7 +32,7 @@ int skaclient_startf_async ( skaclient_cbdata_t *blah) { int fd ; - pid_t pid = child_spawn(prog, argv, envp, &fd, 1) ; + pid_t pid = child_spawn1_socket(prog, argv, envp, &fd) ; if (!pid) return 0 ; if (!skaclient_init(a, fd, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, before, beforelen)) {