Possible leak in libargus

I’ve got a leak in my program (which has 5 CSI cameras connected to libargus) I think i’ve isolated it to libargus, but i’m not sure how to continue debugging from here. After running my program for a short while under valgrind, and stopping it, my leak report shows a lot of small blocks.

==9503== 32 bytes in 1 blocks are still reachable in loss record 12 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E3976F: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 13 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E3978F: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 14 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E397AB: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 15 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E449E3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 16 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44A0B: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 17 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44A33: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 18 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44A5B: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 19 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44A83: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 20 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44AA3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 21 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44AC3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 22 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44AE3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 23 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44B03: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 24 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44B23: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 25 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44B43: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 26 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44B63: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 27 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44B83: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 28 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44BA3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 29 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44BC3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 30 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44BE3: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 31 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44C03: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 32 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44C23: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 33 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44C43: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 34 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44C63: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503== 
==9503== 32 bytes in 1 blocks are still reachable in loss record 35 of 196
==9503==    at 0x4844FC8: malloc (vg_replace_malloc.c:299)
==9503==    by 0x4E44C83: ??? (in /usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so)
==9503==    by 0x400D7CF: call_init.part.0 (in /usr/lib/ld-2.28.so)
==9503==

my loop is pretty simple, it looks like this

while(a->running) {
            Argus::Status status;
            Argus::UniqueObj<EGLStream::Frame> frame(ifc->acquireFrame(Argus::TIMEOUT_INFINITE, &status));

            if (!frame) {
                std::string status_string = argus_status_to_string(status);
                    
                std::cerr << "NO ACTUAL FRAME RETURNED FROM CAMERA " << a->camnum << " (" << status_string << ") " << std::endl;
                a->running = false;
            }                
            else {
                framecnt++;
                if (framecnt % a->decimate != 0) {
                    continue;
                }
            
                {
                    struct fd_time out = {};
                    EGLStream::IFrame *ifr = interface_cast<EGLStream::IFrame>(frame);
                    EGLStream::Image *i = ifr->getImage();
                    {
                        struct timespec ts;
                        clock_gettime(CLOCK_REALTIME, &ts);
                        out.time = ts.tv_sec * 1e9 + ts.tv_nsec;
                    }
                    
                    if (i != NULL) {
                        EGLStream::IImage2D *ii = interface_cast<EGLStream::IImage2D>(i);
                        EGLStream::NV::IImageNativeBuffer *iNativeBuffer = interface_cast<EGLStream::NV::IImageNativeBuffer>(i);
                        std::unique_lock<std::mutex> l(a->mut);
                        
                        out.fd = iNativeBuffer->createNvBuffer(ii->getSize(), NvBufferColorFormat_ABGR32, NvBufferLayout_BlockLinear, &status);
                        
                        if (out.fd >= 0) {
                            if (write(a->pipefd[1], &out, sizeof(out)) < 0) {
                                fprintf(stderr, "pipe write error: %m");
                            } else {
                                a->newframe.wait(l);
                            }
                        } else {
                            std::cerr << "Failed to create nvbuffer, " << argus_status_to_string(status) << std::endl;
                        }
                    }
                }
             }
         }

there’s another frame listening on the other side of the pipe that gets written to toward the end of the loop, and calling NvBufferDestroy on the fd’s that get pulled out.

am i missing something? is there some other cleanup that needs to be done per frame?

Thanks.

Could you build your APP by “cmake -DDISABLE_MULTIPROCESS=ON” to try?

- The DISABLE_MULTIPROCESS option may be provided to use the single-process
         Argus implementation (ie. does not require argus-daemon service):
           'cmake -DDISABLE_MULTIPROCESS=ON ..'