diff options
author | Leah Neukirchen <leah@vuxu.org> | 2023-08-01 18:49:26 +0200 |
---|---|---|
committer | Leah Neukirchen <leah@vuxu.org> | 2023-08-02 13:50:38 +0200 |
commit | f350b6f16c668cd49dc24be3b6dd44c059fe2e0c (patch) | |
tree | beb62542f4a90d688cd77a1512e605da7925d7cb /xe.c | |
parent | 8a2a4899769335bc14c62aef12cdf26f2f487f2a (diff) | |
download | xe-f350b6f16c668cd49dc24be3b6dd44c059fe2e0c.tar.gz xe-f350b6f16c668cd49dc24be3b6dd44c059fe2e0c.tar.xz xe-f350b6f16c668cd49dc24be3b6dd44c059fe2e0c.zip |
properly forward errors on exec, return 123 on any exit status 1-254
Use the CLOEXEC pipe trick to detect if exec happened; read the errno from the pipe if it wasn't closed due to exec.
Diffstat (limited to 'xe.c')
-rw-r--r-- | xe.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/xe.c b/xe.c index f220a82..804833c 100644 --- a/xe.c +++ b/xe.c @@ -99,17 +99,15 @@ mywait() my_child: if (WIFEXITED(status)) { - if (WEXITSTATUS(status) >= 1 && WEXITSTATUS(status) <= 125) { + if (WEXITSTATUS(status) == 255) { + fprintf(stderr, "xe: job %ld [pid %ld] exited with status 255\n", children[i].iter, (long)pid); + exit(124); + } else if (WEXITSTATUS(status) > 0) { if (Fflag) { fprintf(stderr, "xe: job %ld [pid %ld] exited with status %d\n", children[i].iter, (long)pid, WEXITSTATUS(status)); exit(123); } failed = 1; - } else if (WEXITSTATUS(status) == 255) { - fprintf(stderr, "xe: job %ld [pid %ld] exited with status 255\n", children[i].iter, (long)pid); - exit(124); - } else if (WEXITSTATUS(status) > 125) { - exit(WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { fprintf(stderr, "xe: job %ld [pid %ld] terminated by signal %d\n", @@ -232,8 +230,17 @@ run() exit(126); } + unsigned char status; + int alivepipefd[2]; + if (pipe(alivepipefd) < 0) + exit(126); + fcntl(alivepipefd[0], F_SETFD, FD_CLOEXEC); + fcntl(alivepipefd[1], F_SETFD, FD_CLOEXEC); + pid = fork(); if (pid == 0) { // in child + close(alivepipefd[0]); + char iter[32]; snprintf(iter, sizeof iter, "%ld", iterations); setenv("ITER", iter, 1); @@ -268,14 +275,26 @@ run() execvp(args[0], args); - int status = (errno == ENOENT ? 127 : 126); + status = (errno == ENOENT ? 127 : 126); + if (write(alivepipefd[1], &status, 1) != 1) { + /* ignored */ + } fprintf(stderr, "xe: %s: %s\n", args[0], strerror(errno)); - exit(status); + _exit(status); } else if (pid < 0) { // fork failed fprintf(stderr, "xe: %s: %s\n", args[0], strerror(errno)); exit(126); } + close(alivepipefd[1]); + if (read(alivepipefd[0], &status, 1) == 1) { + if (status == 126) + exit(126); + if (status == 127) + exit(127); + } + close(alivepipefd[0]); + if (Lflag) { long iter = iterations; lpid = fork(); |