i3 / i3status

Generates status bar to use with i3bar, dzen2 or xmobar
BSD 3-Clause "New" or "Revised" License
596 stars 251 forks source link

i3status-2.12 memory leak (2019) #330

Open ghost opened 5 years ago

ghost commented 5 years ago

I saw in top that i3status uses 3GiB RAM, after reload the value dropped down to some MiB. But then it increased again: $ while true; do top -b | awk '/i3status/ {print $6,$7,$NF}' ; sleep 10; done 110M 18M i3status 111M 18M i3status 111M 18M i3status 112M 18M i3status 112M 18M i3status 113M 18M i3status 113M 18M i3status 114M 19M i3status 114M 19M i3status 114M 19M i3status

I see that this is not the first mention of this problem. How can I find the root cause? Coverity? Valgrind? Or is there a patch somewhere? I'm using FreeBSD 12.0

regards, A

ghost commented 5 years ago

I read some threads. Here is the minimal config. This seems to be OK, no leak.

general { output_format = i3bar colors = true interval = 5 } order += "tztime local" tztime local { format = " %H:%M %a " }

But when I added locale (not the default!) to the tztime config, then the memory usage began to increase. Other modules (battery, ethernet, wireless) seem to be OK, at least in my quick tests.

Airblader commented 5 years ago

That's interesting information already, thank you. It's a bit surprising, though, since we really only call setlocale and that call seems fine to me.

Could you maybe use valgrind to figure out where memory gets lost? I haven't used it in a while, but something like valgrind --leak-check=yes i3status should work.

ghost commented 5 years ago

The setlocale call in the loop. Here is the patch that fixed the problem, at least for me.


--- src/print_time.c.orig   2019-01-13 11:59:20 UTC
+++ src/print_time.c
@@ -47,7 +47,7 @@ void print_time(yajl_gen json_gen, char *buffer, const
     localtime_r(&t, &tm);

     if (locale != NULL) {
-        setlocale(LC_ALL, locale);
+        setlocale(LC_TIME, locale);
     }

     if (format_time == NULL) {
@@ -69,7 +69,7 @@ void print_time(yajl_gen json_gen, char *buffer, const
     }

     if (locale != NULL) {
-        setlocale(LC_ALL, "");
+        setlocale(LC_TIME, "");
     }

     *outwalk = '\0';
ghost commented 5 years ago

Terrible formatting... replacing LC_ALL with LC_TIME is the key.

Anyway, calling setlocale(LC_ALL, locale); setlocale(LC_ALL, ""); in a loop should not leak. So this is not really related to i3status. The other option would be to handle locale setting like TZ. But that may have side effects in other modules.

I'm satisfied with this patch.

Airblader commented 5 years ago

Yeah, this doesn't really seem like an i3status issue. I wonder if other FreeBSD users can reproduce this?

dummyuser-bot commented 5 years ago

Same issue with wireless, cpu_usage, memory, disk, cpu_temperature. I've tested almost every option (only one running at a time). Config files were taken from https://i3wm.org/i3status/manpage.html but I've changed few paths to match my system. Here are is the result:

-wireless - even bigger leakage when connected -cpu_usage - big leakage -memory - big leakage -disk - "13312 6428 i3status" 1.5 minute later -> "13420 6428 i3status" -cpu_temperature - "13164 6348 i3status" 4 minutes later -> "13360 6412 i3status" -tztime - LC_TIME "13416 6596 i3status" 9 minutes later -> "13588 6660 i3status" -tztime - LC_ALL "13116 6304 i3status" 9 minutes later -> "13348 6432 i3status"

Not tested: -ipv6 -run_watch -path_exists -ethernet

The tests were made with 54e798e3a6dcf5747c3e943b376ae441ee0534a4 build on Linux 64bit.

dummyuser-bot commented 5 years ago

One more test. 130M for 30 minutes.

Here is a comaparison between 54e798e3a6dcf5747c3e943b376ae441ee0534a4 and the Debian 9 version. Same config for both versions:

order += "cpu_usage" order += "cpu_temperature 1" order += "cpu_temperature 2" order += "cpu_temperature 3" order += "cpu_temperature 4" order += "volume master" order += "wireless ..." order += "disk /" order += "tztime local"

$ while true; do top -b | awk '/i3status/ {print $6,$7,$NF}' ; sleep 10; done
18112 7816 i3status     <-- latest version start
18316 7816 i3status
18460 7816 i3status
...
35176 7816 i3status
35264 7816 i3status
...
59260 7816 i3status
59464 7816 i3status
...
99956 7816 i3status
100124 7816 i3status
...
129716 7816 i3status
129828 7816 i3status        <-- 30 Minutes later
5944 5096 i3status      <-- Debian 9 version starts here
6616 5568 i3status
...
6616 5568 i3status
...
6616 5568 i3status      <-- 90 Minutes later