summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2022-01-11 22:25:29 +0100
committerBenBE <BenBE@geshi.org>2022-01-11 22:56:27 +0100
commitd0d9f202c56c1fc8919548418b339d31a6b49c02 (patch)
tree501acaffc28b64f30c5ecf5fc25f370895fce166
parenta0ad0697a8ebb69a183c44d5b812ac1c375c73e5 (diff)
Avoid zombie processes on signal races
The system curses library can handle terminal size changes with SIGWINCH without asking system calls to restart, which effectively stops system calls with -1 and EINTR. An example is ncurses on Linux systems. One of these system calls is waitpid. While waiting for the lsof child to complete, a badly timed SIGWINCH can interrupt the waitpid call, effectively never clearing the state of the child, keeping the zombie until htop exits. Proof of Concept: #include <unistd.h> int main(void) { close(1); close(2); sleep(5); return 0; } Compile this as a replacement "lsof" and put it into your path. Make sure that it's called instead of the real lsof. Press "l" to list open files and resize your terminal within the next 5 seconds. You will see that a zombie process is kept by htop when the timeout finishes.
-rw-r--r--OpenFilesScreen.c10
-rw-r--r--TraceScreen.c5
2 files changed, 10 insertions, 5 deletions
diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c
index 34367ebc..2d191692 100644
--- a/OpenFilesScreen.c
+++ b/OpenFilesScreen.c
@@ -9,6 +9,7 @@ in the source distribution for its full text.
#include "OpenFilesScreen.h"
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
@@ -197,10 +198,11 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
fclose(fd);
int wstatus;
- if (waitpid(child, &wstatus, 0) == -1) {
- pdata->error = 1;
- return pdata;
- }
+ while (waitpid(child, &wstatus, 0) == -1)
+ if (errno != EINTR) {
+ pdata->error = 1;
+ return pdata;
+ }
if (!WIFEXITED(wstatus)) {
pdata->error = 1;
diff --git a/TraceScreen.c b/TraceScreen.c
index c726394a..c3a94492 100644
--- a/TraceScreen.c
+++ b/TraceScreen.c
@@ -10,6 +10,7 @@ in the source distribution for its full text.
#include "TraceScreen.h"
#include <assert.h>
+#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
@@ -47,7 +48,9 @@ void TraceScreen_delete(Object* cast) {
TraceScreen* this = (TraceScreen*) cast;
if (this->child > 0) {
kill(this->child, SIGTERM);
- waitpid(this->child, NULL, 0);
+ while (waitpid(this->child, NULL, 0) == -1)
+ if (errno != EINTR)
+ break;
}
if (this->strace) {

© 2014-2024 Faster IT GmbH | imprint | privacy policy