summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/forkfd/forkfd.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index 86e109358c..5d62f88149 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -25,9 +25,8 @@
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
-# define _POSIX_C_SOURCE 200809L
-# define _XOPEN_SOURCE 700
#endif
+
#include "forkfd.h"
#include <sys/types.h>
@@ -44,6 +43,7 @@
#include <unistd.h>
#ifdef __linux__
+# define HAVE_WAIT4 1
# if (defined(__GLIBC__) && (__GLIBC__ << 16) + __GLIBC_MINOR__ >= 0x207) || defined(__BIONIC__)
# include <sys/eventfd.h>
# define HAVE_EVENTFD 1
@@ -56,6 +56,10 @@
#if _POSIX_VERSION-0 >= 200809L || _XOPEN_VERSION-0 >= 500
# define HAVE_WAITID 1
#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \
+ defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+# define HAVE_WAIT4 1
+#endif
#if defined(__APPLE__)
/* Up until OS X 10.7, waitid(P_ALL, ...) will return success, but will not
@@ -188,12 +192,33 @@ static int isChildReady(pid_t pid, siginfo_t *info)
}
#endif
+static void convertStatusToForkfdInfo(int status, struct forkfd_info *info)
+{
+ if (WIFEXITED(status)) {
+ info->code = CLD_EXITED;
+ info->status = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ info->code = CLD_KILLED;
+# ifdef WCOREDUMP
+ if (WCOREDUMP(status))
+ info->code = CLD_DUMPED;
+# endif
+ info->status = WTERMSIG(status);
+ }
+}
+
static int tryReaping(pid_t pid, struct pipe_payload *payload)
{
/* reap the child */
-#ifdef HAVE_WAITID
+#if defined(HAVE_WAIT4)
+ int status;
+ if (wait4(pid, &status, WNOHANG, &payload->rusage) <= 0)
+ return 0;
+ convertStatusToForkfdInfo(status, &payload->info);
+#else
+# if defined(HAVE_WAITID)
if (waitid_works) {
- // we have waitid(2), which fills in siginfo_t for us
+ /* we have waitid(2), which gets us some payload values on some systems */
siginfo_t info;
info.si_pid = 0;
int ret = waitid(P_PID, pid, &info, WEXITED | WNOHANG) == 0 && info.si_pid == pid;
@@ -202,30 +227,20 @@ static int tryReaping(pid_t pid, struct pipe_payload *payload)
payload->info.code = info.si_code;
payload->info.status = info.si_status;
-# ifdef __linux__
+# ifdef __linux__
payload->rusage.ru_utime.tv_sec = info.si_utime / CLOCKS_PER_SEC;
payload->rusage.ru_utime.tv_usec = info.si_utime % CLOCKS_PER_SEC;
payload->rusage.ru_stime.tv_sec = info.si_stime / CLOCKS_PER_SEC;
payload->rusage.ru_stime.tv_usec = info.si_stime % CLOCKS_PER_SEC;
-# endif
+# endif
return 1;
}
-#endif
+# endif // HAVE_WAITID
int status;
if (waitpid(pid, &status, WNOHANG) <= 0)
return 0; // child did not change state
-
- if (WIFEXITED(status)) {
- payload->info.code = CLD_EXITED;
- payload->info.status = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- payload->info.code = CLD_KILLED;
-# ifdef WCOREDUMP
- if (WCOREDUMP(status))
- payload->info.code = CLD_DUMPED;
-# endif
- payload->info.status = WTERMSIG(status);
- }
+ convertStatusToForkfdInfo(status, &payload->info);
+#endif // !HAVE_WAIT4
return 1;
}