123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- From 1a8f65f2b8d33dc09f6ccb6a7bd6ca85760cf720 Mon Sep 17 00:00:00 2001
- From: Stefan O'Rear <sorear@fastmail.com>
- Date: Thu, 3 Sep 2020 05:20:45 -0400
- Subject: [PATCH 07/16] Emulate wait4 using waitid
- riscv32 and future architectures lack wait4.
- waitpid is required by POSIX to be a cancellation point. pclose is
- specified as undefined if a cancellation occurs, so it would be
- permitted for it to call a cancellable wait function; however, as a
- quality of implementation matter, pclose must close the pipe fd before
- it can wait (consider popen("yes","r")) and if the wait could be
- interrupted the pipe FILE would be left in an intermediate state that
- portable software cannot recover from, so the only useful behavior is
- for pclose to NOT be a cancellation point. We therefore support both at
- a small cost in code size.
- wait4 is historically not a cancellation point in musl; we retain that
- since we need the non-cancellable version of __wait4 anyway.
- ---
- src/internal/__wait4.c | 55 ++++++++++++++++++++++++++++++++++++++++++
- src/internal/syscall.h | 12 +++++++++
- src/linux/wait4.c | 2 +-
- src/process/waitpid.c | 2 +-
- src/stdio/pclose.c | 2 +-
- src/unistd/faccessat.c | 6 ++++-
- 6 files changed, 75 insertions(+), 4 deletions(-)
- create mode 100644 src/internal/__wait4.c
- diff --git a/src/internal/__wait4.c b/src/internal/__wait4.c
- new file mode 100644
- index 00000000..04d7dc64
- --- /dev/null
- +++ b/src/internal/__wait4.c
- @@ -0,0 +1,55 @@
- +#include <sys/wait.h>
- +#include "syscall.h"
- +
- +#ifndef SYS_wait4
- +hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
- +{
- + idtype_t t;
- + int r;
- + siginfo_t info;
- +
- + info.si_pid = 0;
- + if (pid < -1) {
- + t = P_PGID;
- + pid = -pid;
- + } else if (pid == -1) {
- + t = P_ALL;
- + } else if (pid == 0) {
- + t = P_PGID;
- + } else {
- + t = P_PID;
- + }
- +
- + if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru);
- + else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru);
- +
- + if (r<0) return r;
- +
- + if (info.si_pid && status) {
- + int sw=0;
- + switch (info.si_code) {
- + case CLD_CONTINUED:
- + sw = 0xffff;
- + break;
- + case CLD_DUMPED:
- + sw = info.si_status&0x7f | 0x80;
- + break;
- + case CLD_EXITED:
- + sw = (info.si_status&0xff) << 8;
- + break;
- + case CLD_KILLED:
- + sw = info.si_status&0x7f;
- + break;
- + case CLD_STOPPED:
- + case CLD_TRAPPED:
- + /* see ptrace(2); the high bits of si_status can contain */
- + /* PTRACE_EVENT_ values which must be preserved */
- + sw = (info.si_status << 8) + 0x7f;
- + break;
- + }
- + *status = sw;
- + }
- +
- + return info.si_pid;
- +}
- +#endif
- diff --git a/src/internal/syscall.h b/src/internal/syscall.h
- index 4f41e1dc..27642938 100644
- --- a/src/internal/syscall.h
- +++ b/src/internal/syscall.h
- @@ -5,6 +5,8 @@
- #include <errno.h>
- #include <sys/syscall.h>
- #include "syscall_arch.h"
- +#define __NEED_pid_t
- +#include <bits/alltypes.h>
-
- #ifndef SYSCALL_RLIM_INFINITY
- #define SYSCALL_RLIM_INFINITY (~0ULL)
- @@ -395,4 +397,14 @@ hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
-
- hidden void *__vdsosym(const char *, const char *);
-
- +#ifdef SYS_wait4
- +static inline pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
- +{
- + if (cp) return __syscall_cp(SYS_wait4, pid, status, options, kru);
- + else return __syscall(SYS_wait4, pid, status, options, kru);
- +}
- +#else
- +hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp);
- +#endif
- +
- #endif
- diff --git a/src/linux/wait4.c b/src/linux/wait4.c
- index 83650e34..32652dc2 100644
- --- a/src/linux/wait4.c
- +++ b/src/linux/wait4.c
- @@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
- }
- #endif
- char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0;
- - r = __syscall(SYS_wait4, pid, status, options, dest);
- + r = __wait4(pid, status, options, dest, 0);
- if (r>0 && ru && sizeof(time_t) > sizeof(long)) {
- long kru[4];
- memcpy(kru, dest, 4*sizeof(long));
- diff --git a/src/process/waitpid.c b/src/process/waitpid.c
- index 1b65bf05..e5ff27ca 100644
- --- a/src/process/waitpid.c
- +++ b/src/process/waitpid.c
- @@ -3,5 +3,5 @@
-
- pid_t waitpid(pid_t pid, int *status, int options)
- {
- - return syscall_cp(SYS_wait4, pid, status, options, 0);
- + return __wait4(pid, status, options, 0, 1);
- }
- diff --git a/src/stdio/pclose.c b/src/stdio/pclose.c
- index 080a4262..b60d8f2c 100644
- --- a/src/stdio/pclose.c
- +++ b/src/stdio/pclose.c
- @@ -7,7 +7,7 @@ int pclose(FILE *f)
- int status, r;
- pid_t pid = f->pipe_pid;
- fclose(f);
- - while ((r=__syscall(SYS_wait4, pid, &status, 0, 0)) == -EINTR);
- + while ((r=__wait4(pid, &status, 0, 0, 0)) == -EINTR);
- if (r<0) return __syscall_ret(r);
- return status;
- }
- diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c
- index 557503eb..8e8689c1 100644
- --- a/src/unistd/faccessat.c
- +++ b/src/unistd/faccessat.c
- @@ -39,7 +39,6 @@ int faccessat(int fd, const char *filename, int amode, int flag)
- char stack[1024];
- sigset_t set;
- pid_t pid;
- - int status;
- int ret, p[2];
-
- if (pipe2(p, O_CLOEXEC)) return __syscall_ret(-EBUSY);
- @@ -53,7 +52,12 @@ int faccessat(int fd, const char *filename, int amode, int flag)
- if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret))
- ret = -EBUSY;
- __syscall(SYS_close, p[0]);
- +#ifdef SYS_wait4
- + int status;
- __syscall(SYS_wait4, pid, &status, __WCLONE, 0);
- +#else
- + __syscall(SYS_waitid, P_PID, pid, &(siginfo_t){0}, __WCLONE|WEXITED, 0);
- +#endif
-
- __restore_sigs(&set);
-
- --
- 2.29.2
|