0007-Emulate-wait4-using-waitid.patch 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. From 1a8f65f2b8d33dc09f6ccb6a7bd6ca85760cf720 Mon Sep 17 00:00:00 2001
  2. From: Stefan O'Rear <sorear@fastmail.com>
  3. Date: Thu, 3 Sep 2020 05:20:45 -0400
  4. Subject: [PATCH 07/16] Emulate wait4 using waitid
  5. riscv32 and future architectures lack wait4.
  6. waitpid is required by POSIX to be a cancellation point. pclose is
  7. specified as undefined if a cancellation occurs, so it would be
  8. permitted for it to call a cancellable wait function; however, as a
  9. quality of implementation matter, pclose must close the pipe fd before
  10. it can wait (consider popen("yes","r")) and if the wait could be
  11. interrupted the pipe FILE would be left in an intermediate state that
  12. portable software cannot recover from, so the only useful behavior is
  13. for pclose to NOT be a cancellation point. We therefore support both at
  14. a small cost in code size.
  15. wait4 is historically not a cancellation point in musl; we retain that
  16. since we need the non-cancellable version of __wait4 anyway.
  17. ---
  18. src/internal/__wait4.c | 55 ++++++++++++++++++++++++++++++++++++++++++
  19. src/internal/syscall.h | 12 +++++++++
  20. src/linux/wait4.c | 2 +-
  21. src/process/waitpid.c | 2 +-
  22. src/stdio/pclose.c | 2 +-
  23. src/unistd/faccessat.c | 6 ++++-
  24. 6 files changed, 75 insertions(+), 4 deletions(-)
  25. create mode 100644 src/internal/__wait4.c
  26. diff --git a/src/internal/__wait4.c b/src/internal/__wait4.c
  27. new file mode 100644
  28. index 00000000..04d7dc64
  29. --- /dev/null
  30. +++ b/src/internal/__wait4.c
  31. @@ -0,0 +1,55 @@
  32. +#include <sys/wait.h>
  33. +#include "syscall.h"
  34. +
  35. +#ifndef SYS_wait4
  36. +hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
  37. +{
  38. + idtype_t t;
  39. + int r;
  40. + siginfo_t info;
  41. +
  42. + info.si_pid = 0;
  43. + if (pid < -1) {
  44. + t = P_PGID;
  45. + pid = -pid;
  46. + } else if (pid == -1) {
  47. + t = P_ALL;
  48. + } else if (pid == 0) {
  49. + t = P_PGID;
  50. + } else {
  51. + t = P_PID;
  52. + }
  53. +
  54. + if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru);
  55. + else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru);
  56. +
  57. + if (r<0) return r;
  58. +
  59. + if (info.si_pid && status) {
  60. + int sw=0;
  61. + switch (info.si_code) {
  62. + case CLD_CONTINUED:
  63. + sw = 0xffff;
  64. + break;
  65. + case CLD_DUMPED:
  66. + sw = info.si_status&0x7f | 0x80;
  67. + break;
  68. + case CLD_EXITED:
  69. + sw = (info.si_status&0xff) << 8;
  70. + break;
  71. + case CLD_KILLED:
  72. + sw = info.si_status&0x7f;
  73. + break;
  74. + case CLD_STOPPED:
  75. + case CLD_TRAPPED:
  76. + /* see ptrace(2); the high bits of si_status can contain */
  77. + /* PTRACE_EVENT_ values which must be preserved */
  78. + sw = (info.si_status << 8) + 0x7f;
  79. + break;
  80. + }
  81. + *status = sw;
  82. + }
  83. +
  84. + return info.si_pid;
  85. +}
  86. +#endif
  87. diff --git a/src/internal/syscall.h b/src/internal/syscall.h
  88. index 4f41e1dc..27642938 100644
  89. --- a/src/internal/syscall.h
  90. +++ b/src/internal/syscall.h
  91. @@ -5,6 +5,8 @@
  92. #include <errno.h>
  93. #include <sys/syscall.h>
  94. #include "syscall_arch.h"
  95. +#define __NEED_pid_t
  96. +#include <bits/alltypes.h>
  97. #ifndef SYSCALL_RLIM_INFINITY
  98. #define SYSCALL_RLIM_INFINITY (~0ULL)
  99. @@ -395,4 +397,14 @@ hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
  100. hidden void *__vdsosym(const char *, const char *);
  101. +#ifdef SYS_wait4
  102. +static inline pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
  103. +{
  104. + if (cp) return __syscall_cp(SYS_wait4, pid, status, options, kru);
  105. + else return __syscall(SYS_wait4, pid, status, options, kru);
  106. +}
  107. +#else
  108. +hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp);
  109. +#endif
  110. +
  111. #endif
  112. diff --git a/src/linux/wait4.c b/src/linux/wait4.c
  113. index 83650e34..32652dc2 100644
  114. --- a/src/linux/wait4.c
  115. +++ b/src/linux/wait4.c
  116. @@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
  117. }
  118. #endif
  119. char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0;
  120. - r = __syscall(SYS_wait4, pid, status, options, dest);
  121. + r = __wait4(pid, status, options, dest, 0);
  122. if (r>0 && ru && sizeof(time_t) > sizeof(long)) {
  123. long kru[4];
  124. memcpy(kru, dest, 4*sizeof(long));
  125. diff --git a/src/process/waitpid.c b/src/process/waitpid.c
  126. index 1b65bf05..e5ff27ca 100644
  127. --- a/src/process/waitpid.c
  128. +++ b/src/process/waitpid.c
  129. @@ -3,5 +3,5 @@
  130. pid_t waitpid(pid_t pid, int *status, int options)
  131. {
  132. - return syscall_cp(SYS_wait4, pid, status, options, 0);
  133. + return __wait4(pid, status, options, 0, 1);
  134. }
  135. diff --git a/src/stdio/pclose.c b/src/stdio/pclose.c
  136. index 080a4262..b60d8f2c 100644
  137. --- a/src/stdio/pclose.c
  138. +++ b/src/stdio/pclose.c
  139. @@ -7,7 +7,7 @@ int pclose(FILE *f)
  140. int status, r;
  141. pid_t pid = f->pipe_pid;
  142. fclose(f);
  143. - while ((r=__syscall(SYS_wait4, pid, &status, 0, 0)) == -EINTR);
  144. + while ((r=__wait4(pid, &status, 0, 0, 0)) == -EINTR);
  145. if (r<0) return __syscall_ret(r);
  146. return status;
  147. }
  148. diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c
  149. index 557503eb..8e8689c1 100644
  150. --- a/src/unistd/faccessat.c
  151. +++ b/src/unistd/faccessat.c
  152. @@ -39,7 +39,6 @@ int faccessat(int fd, const char *filename, int amode, int flag)
  153. char stack[1024];
  154. sigset_t set;
  155. pid_t pid;
  156. - int status;
  157. int ret, p[2];
  158. if (pipe2(p, O_CLOEXEC)) return __syscall_ret(-EBUSY);
  159. @@ -53,7 +52,12 @@ int faccessat(int fd, const char *filename, int amode, int flag)
  160. if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret))
  161. ret = -EBUSY;
  162. __syscall(SYS_close, p[0]);
  163. +#ifdef SYS_wait4
  164. + int status;
  165. __syscall(SYS_wait4, pid, &status, __WCLONE, 0);
  166. +#else
  167. + __syscall(SYS_waitid, P_PID, pid, &(siginfo_t){0}, __WCLONE|WEXITED, 0);
  168. +#endif
  169. __restore_sigs(&set);
  170. --
  171. 2.29.2