llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.85k stars 11.47k forks source link

ASAN report wrong memory leak on MUSL libc OS #61698

Open joyhou-hw opened 1 year ago

joyhou-hw commented 1 year ago

The code use std::thread create a non return thread. while the main funciton not join this thread, and return directly.

Compile with -fsanitize=address will report an 8-bit and 48-bit leak, that is thread_struct and pointer, on musl Linux system. But will OK on glibc OS. I am not sure this is an issue in ASan or in musl libc.

#include <string>
#include <chrono>
#include <thread>
#include <getopt.h>
#include <iostream>
#include <sys/time.h>
#include <unistd.h>
#include <sys/prctl.h>

namespace {
class TestTmp {
public:
    TestTmp() :
        procMsgThread_()
    {
        std::cout << "TestTmp construct: " << std::endl;
    }
    virtual ~TestTmp() {
        std::cout << "TestTmp destruct: " << std::endl;
        if (procMsgThread_.joinable()) {
            procMsgThread_.join();
        }
    }
    void Init() {
        procMsgThread_ = std::thread(&TestTmp::BackgroundWorker, this);
    }
    void BackgroundWorker()
    {
        std::cout << "BackgroundWorker begin." << std::endl;
        static_cast<void>(prctl(PR_SET_NAME, "test_work"));
        while (true) {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
    std::thread procMsgThread_;
};

static TestTmp * longTimeObj = new TestTmp();
}

int main(int argc,char *argv[])
{

    std::cout << "Process is started."<< std::endl;
    longTimeObj->Init();
    sleep(5);
    return EXIT_SUCCESS;
}
DimitryAndric commented 1 year ago

With std::thread, you should either call std::thread::join or std::thread::detach, otherwise the runtime may invoke std::terminate when the thread's destructor is called. Depending on the particular mechanism used to manage threads, this may or may not lead to leaks (or crashes!).

vitalybuka commented 1 year ago

static near longTimeObj let compiler to eliminate that as global, so you have a leak report. Works as intended to me.

joyhou-hw commented 1 year ago

I did a simple analysis on Glibc OS. That 8-bit pointer addr exists in the stack space of the child thread. This causes asan to mark the content as reachable when scaning for stack space addresses. And, when only use the pthread interface to create a thread(in c, not c++), that leak will not reported in the MUSL OS.

Currently, May be only the std::thread and MUSL libraries report this leak. The leak pointer address is not found during stack scanning.

Looks likestd::thread uses some features I don't know about?