Bug 230458

Summary: net/boinc_curses: leaking memory
Product: Ports & Packages Reporter: Johannes Lundberg <johalun0>
Component: Individual Port(s)Assignee: freebsd-ports-bugs (Nobody) <ports-bugs>
Status: Open ---    
Severity: Affects Some People CC: danfe
Priority: ---    
Version: Latest   
Hardware: Any   
OS: Any   

Description Johannes Lundberg 2018-08-08 14:48:10 UTC

As the title says. 

Name           : boinc_curses
Version        : 0.2.3

FreeBSD jd 12.0-CURRENT FreeBSD 12.0-CURRENT #18 bd020f21ebb(master): Wed Aug  8 08:33:12 BST 2018     root@jd:/usr/obj/usr/src/amd64.amd64/sys/JD-NODEBUG  amd64

I notice this on one machine that has little memory and no swap, boinc_curses gets killed at least once per day:

pid 1012 (boinc_curses), uid 0, was killed: out of swap space

Then I checked on my other machine with swap and more memory, when I have boinc_curses running free memory slowly decreases, about 1 MB / second.
Comment 1 Johannes Lundberg 2018-08-08 14:56:02 UTC
procstat -v <boinc_curses pid>

show an ever increasing amount of PRES.
Comment 2 Alexey Dokuchaev freebsd_committer 2020-07-10 06:21:14 UTC
I've spend two days debugging this, and here are my findings:

1. It does indeed leak memory, at various rates, but it's pretty visible in the top(1) output. Yes, it would eventually be killed due to running out of swap space (within a day or two, depending on the activity and amount of RAM available).

2. The leak does not happen because of improper use of `net/boinc_client' RPC C++ APIs.  All of them seem to call .clear() methods and `delete' as needed. I've commented out most of the RPC calls except init+auth+get_state and it still leaks memory.  However, my quick program which simply does this:

> rpc.init("localhost", GUI_RPC_PORT);
> rpc.authorize(passkey);
> for (;;) {
>     CC_STATE state;
>     rpc.get_state(state);
>     sleep(1);
>     state.clear(); // technically not needed, get_state() does this
> }
does NOT leak.

3. I've started to comment out other function calls one by one and surprisingly found that the leaks had stopped once I've commented out "halfdelay(REFRESH_RATE)" calls.  After that the `boinc_curses' process worked overnight using stable 58M of RAM.

4. I've built it with -fsanitize=address -fno-omit-frame-pointer, it found two stack buffer overruns in formatter[] arrays, but no other bugs.

5. I did not try to investigate why calling halfdelay() makes it leak.

That said, if you have better understanding of what's going on, please share your thoughts.  If not, but you can confirm that leaks do not occur with commented out "halfdelay(REFRESH_RATE)" calls, I guess we can commit it as "good enough" fix for the time being.