summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-10-10 19:23:43 +0200
committerSébastien Helleu <flashcode@flashtux.org>2023-10-10 19:23:43 +0200
commit02a05f63d5d84e1adedf2352721c418ef3ba8c76 (patch)
tree337a793b34e30fa958e10482ec4f6f0680e5f025 /src
parent408901d772a92fbf62b2e6c8ad3345e36d316d9a (diff)
downloadweechat-02a05f63d5d84e1adedf2352721c418ef3ba8c76.zip
core: fix zombie processes remaining after the end of forked processes (closes #1994)
The clean of processes with waitpid() is now delayed after the kill(), so that there are no more zombies. In addition, this can be done manually if needed with `/sys waitpid`.
Diffstat (limited to 'src')
-rw-r--r--src/core/hook/wee-hook-connect.c2
-rw-r--r--src/core/hook/wee-hook-process.c3
-rw-r--r--src/core/wee-command.c16
-rw-r--r--src/core/wee-hook.c30
-rw-r--r--src/core/wee-hook.h1
-rw-r--r--src/core/wee-sys.c19
-rw-r--r--src/core/wee-sys.h1
-rw-r--r--src/plugins/xfer/xfer-network.c3
8 files changed, 68 insertions, 7 deletions
diff --git a/src/core/hook/wee-hook-connect.c b/src/core/hook/wee-hook-connect.c
index 81e402eca..d03fe4bec 100644
--- a/src/core/hook/wee-hook-connect.c
+++ b/src/core/hook/wee-hook-connect.c
@@ -270,7 +270,7 @@ hook_connect_free_data (struct t_hook *hook)
if (HOOK_CONNECT(hook, child_pid) > 0)
{
kill (HOOK_CONNECT(hook, child_pid), SIGKILL);
- waitpid (HOOK_CONNECT(hook, child_pid), NULL, 0);
+ hook_schedule_clean_children ();
HOOK_CONNECT(hook, child_pid) = 0;
}
if (HOOK_CONNECT(hook, child_read) != -1)
diff --git a/src/core/hook/wee-hook-process.c b/src/core/hook/wee-hook-process.c
index ff676dffc..42f0d2a72 100644
--- a/src/core/hook/wee-hook-process.c
+++ b/src/core/hook/wee-hook-process.c
@@ -603,7 +603,6 @@ hook_process_timer_cb (const void *pointer, void *data, int remaining_calls)
((float)HOOK_PROCESS(hook_process, timeout)) / 1000);
}
kill (HOOK_PROCESS(hook_process, child_pid), SIGKILL);
- usleep (1000);
unhook (hook_process);
}
else
@@ -863,7 +862,7 @@ hook_process_free_data (struct t_hook *hook)
if (HOOK_PROCESS(hook, child_pid) > 0)
{
kill (HOOK_PROCESS(hook, child_pid), SIGKILL);
- waitpid (HOOK_PROCESS(hook, child_pid), NULL, 0);
+ hook_schedule_clean_children ();
HOOK_PROCESS(hook, child_pid) = 0;
}
if (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN]) != -1)
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index 64fb1ea08..7520570a7 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -6795,6 +6795,12 @@ COMMAND_CALLBACK(sys)
return WEECHAT_RC_OK;
}
+ if (string_strcmp (argv[1], "waitpid") == 0)
+ {
+ sys_waitpid ();
+ return WEECHAT_RC_OK;
+ }
+
COMMAND_ERROR;
}
@@ -9273,15 +9279,19 @@ command_init ()
NULL, "sys",
N_("system actions"),
"get rlimit|rusage"
- " || suspend",
+ " || suspend"
+ " || waitpid",
N_(" get: display system info\n"
" rlimit: display resource limits "
"(see /help weechat.startup.sys_rlimit and \"man getrlimit\")\n"
" rusage: display resource usage (see \"man getrusage\")\n"
"suspend: suspend WeeChat and go back to the shell, by sending "
- "signal SIGTSTP to the WeeChat process"),
+ "signal SIGTSTP to the WeeChat process\n"
+ "waitpid: acknowledge the end of children processes (to prevent "
+ "\"zombie\" processes)"),
"get rlimit|rusage"
- " || suspend",
+ " || suspend"
+ " || waitpid",
&command_sys, NULL, NULL);
hook_command (
NULL, "toggle",
diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c
index 758052a72..d0c120640 100644
--- a/src/core/wee-hook.c
+++ b/src/core/wee-hook.c
@@ -38,6 +38,7 @@
#include "wee-log.h"
#include "wee-signal.h"
#include "wee-string.h"
+#include "wee-sys.h"
#include "wee-util.h"
#include "../gui/gui-chat.h"
#include "../plugins/plugin.h"
@@ -628,6 +629,35 @@ hook_set (struct t_hook *hook, const char *property, const char *value)
}
/*
+ * Callback used to clean all children (forked processes) by acknowledging
+ * their end.
+ */
+
+int
+hook_timer_clean_children_cb (const void *pointer, void *data,
+ int remaining_calls)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) remaining_calls;
+
+ sys_waitpid ();
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Schedule a cleanup timer to clean children (forked processes).
+ */
+
+void
+hook_schedule_clean_children ()
+{
+ hook_timer (NULL, 100, 0, 1, &hook_timer_clean_children_cb, NULL, NULL);
+}
+
+/*
* Unhooks something.
*/
diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h
index bebb0419e..8ae79a3c6 100644
--- a/src/core/wee-hook.h
+++ b/src/core/wee-hook.h
@@ -146,6 +146,7 @@ extern void hook_callback_end (struct t_hook *hook,
extern char *hook_get_description (struct t_hook *hook);
extern void hook_set (struct t_hook *hook, const char *property,
const char *value);
+extern void hook_schedule_clean_children ();
extern void unhook (struct t_hook *hook);
extern void unhook_all_plugin (struct t_weechat_plugin *plugin,
const char *subplugin);
diff --git a/src/core/wee-sys.c b/src/core/wee-sys.c
index 8bcb3226a..7560b80aa 100644
--- a/src/core/wee-sys.c
+++ b/src/core/wee-sys.c
@@ -32,6 +32,7 @@
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
+#include <sys/wait.h>
#include "weechat.h"
#include "wee-config.h"
@@ -341,3 +342,21 @@ sys_display_rusage ()
"getrusage");
#endif /* HAVE_SYS_RESOURCE_H */
}
+
+/*
+ * Calls waitpid() to acknowledge the end of forked processes, thus preventing
+ * them to become zombies.
+ */
+
+void
+sys_waitpid ()
+{
+ int i;
+
+ /* acknowledge the end of up to 42 forked processes */
+ i = 0;
+ while ((i < 42) && (waitpid (-1, NULL, WNOHANG) > 0))
+ {
+ i++;
+ }
+}
diff --git a/src/core/wee-sys.h b/src/core/wee-sys.h
index d78f6fdb9..eb4e7bcb9 100644
--- a/src/core/wee-sys.h
+++ b/src/core/wee-sys.h
@@ -31,5 +31,6 @@ struct t_rlimit_resource
extern void sys_setrlimit ();
extern void sys_display_rlimit ();
extern void sys_display_rusage ();
+extern void sys_waitpid ();
#endif /* WEECHAT_SYS_H */
diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c
index 8f7609bb3..3c7b63338 100644
--- a/src/plugins/xfer/xfer-network.c
+++ b/src/plugins/xfer/xfer-network.c
@@ -483,7 +483,8 @@ xfer_network_child_kill (struct t_xfer *xfer)
if (xfer->child_pid > 0)
{
kill (xfer->child_pid, SIGKILL);
- waitpid (xfer->child_pid, NULL, 0);
+ weechat_command (weechat_buffer_search_main (),
+ "/mute /wait 100ms /sys waitpid");
xfer->child_pid = 0;
}