1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-12-11 09:27:32 +02:00
openwrt-xburst/package/hotplug2/patches/100-env_memleak.patch
nbd 09fc3a65d9 Fix a memory leak in hotplug2 environment handling.
Bump hotplug2 to the latest svn revision, remove obsolete patches.

Memory leak is caused by the way hotplug2 handles environment variables,
using setenv() and unsetenv(). setenv() creates copies of the supplied
strings, but, due to a POSIX blunder, these copies are never destroyed
by unsetenv(), neither in glibc nor uclibc - not until the program
terminates.

Since some events are handled directly in the main process, even when
configured with the "fork" worker, hotplug2 memory usage will keep
growing over time. This can be observed by running "udevtrigger" and
noting the increase in hotplug2 VmRSS after each run.

This patch uses putenv() instead, which leaves storage management to
the caller, so that we can explicitly delete stuff when it's no longer
needed.

Signed-off-by: Aleksandar Radovanovic <biblbroks@sezampro.rs>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18725 3c298f89-4303-0410-b956-a3cf2f4a3e73
2009-12-09 18:50:49 +00:00

65 lines
1.5 KiB
Diff

diff -Naur a/action.c b/action.c
--- a/action.c 2009-11-18 13:15:21.000000000 +0000
+++ b/action.c 2009-11-18 13:11:19.000000000 +0000
@@ -31,6 +31,30 @@
}
/**
+ * Creates a "key=value" string from the given key and value
+ *
+ * @1 Key
+ * @2 Value
+ *
+ * Returns: Newly allocated string in "key=value" form
+ *
+ */
+static char* alloc_env(const char *key, const char *value) {
+ size_t keylen, vallen;
+ char *combined;
+
+ keylen = strlen(key);
+ vallen = strlen(value) + 1;
+
+ combined = xmalloc(keylen + vallen + 1);
+ memcpy(combined, key, keylen);
+ combined[keylen] = '=';
+ memcpy(&combined[keylen + 1], value, vallen);
+
+ return combined;
+}
+
+/**
* Choose what action should be taken according to passed settings.
*
* @1 Hotplug settings
@@ -41,16 +65,25 @@
*/
void action_perform(struct settings_t *settings, struct uevent_t *event) {
int i;
+ char **env;
+
+ env = xmalloc(sizeof(char *) * event->env_vars_c);
+
+ for (i = 0; i < event->env_vars_c; i++) {
+ env[i] = alloc_env(event->env_vars[i].key, event->env_vars[i].value);
+ putenv(env[i]);
+ }
- for (i = 0; i < event->env_vars_c; i++)
- setenv(event->env_vars[i].key, event->env_vars[i].value, 1);
-
if (settings->dumb == 0) {
ruleset_execute(&settings->rules, event, settings);
} else {
action_dumb(settings, event);
}
- for (i = 0; i < event->env_vars_c; i++)
+ for (i = 0; i < event->env_vars_c; i++) {
unsetenv(event->env_vars[i].key);
+ free(env[i]);
+ }
+
+ free(env);
}