From 95100aa8fa3182f3b066bdc5927b0a78c37550aa Mon Sep 17 00:00:00 2001
From: huangkaibin <huangkaibin@huawei.com>
Date: Mon, 23 Jul 2018 17:58:18 +0800
Subject: [PATCH] systemd-udevd: Call malloc_trim to return memory to OS
 immediately in forked children.

hen there are many events from kernel, memory used to store these events(in event_list)
will be large, may be up to 100M. The forked child process will have a copy of these events and
release them using free. But since glibc will release memory to OS immediately, and if this child process
is stuck due I/O waiting(in D state), these memory will never be released until it is recoveried from D-state.
When there are so many such child processes, it will eat up much memory from system.
This patch fix this problem by invoking glibc's malloc_trim to release memory immediately when the child is forked.
---
 meson.build      |  6 ++++++
 src/udev/udevd.c | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/meson.build b/meson.build
index c14540a..5ee2fa7 100644
--- a/meson.build
+++ b/meson.build
@@ -518,6 +518,12 @@ else
         conf.set10('HAVE_GETRANDOM', have)
 endif
 
+if cc.has_function('malloc_trim', prefix : '''#include <malloc.h>''')
+        conf.set10('HAVE_MALLOC_TRIM', true)
+else
+        conf.set10('HAVE_MALLOC_TRIM', false)
+endif
+
 #####################################################################
 
 sed = find_program('sed')
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index c1119c3..62f1c44 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -27,6 +27,9 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#ifdef HAVE_MALLOC_TRIM
+#include <malloc.h>
+#endif
 
 #include "sd-daemon.h"
 #include "sd-event.h"
@@ -233,6 +236,15 @@ static void worker_spawn(Manager *manager, struct event *event) {
 
                 manager->event = sd_event_unref(manager->event);
 
+#ifdef HAVE_MALLOC_TRIM
+                /* unused memory inherits from parent has been freed, but it will
+                 * not release to OS immediately. We do the optimization by invoking
+                 * glibc's malloc_trim to force these unused memory to return to OS immediately.
+                 * Otherwise when there are many forked process, it will eat up system's memory,
+                 * and will cause OOM problem.
+                 */
+                malloc_trim(0);
+#endif
                 sigfillset(&mask);
                 fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
                 if (fd_signal < 0) {
-- 
1.8.3.1

