In lib/Support/Unix/Signals.inc there is an occasional memory leak, whenever
the function CreateSigAltStack is called multiple times in certain conditions.
To reproduce the bug, just run
valgrind --leak-check=full opt -o /dev/null /dev/null
OS: Ubuntu 18.04
Valgrind version: 3.13.0
llvm version: 7.0.0 (opt-7 system installation in ubuntu, but for what I saw in the sources it affects llvm 8.0.0 as well)
You should be on a Unix system with sigaltstack available.
This is the leak report I get from Valgrind
$ valgrind --leak-check=full opt-7 -o /dev/null /dev/null ==27771== Memcheck, a memory error detector ==27771== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==27771== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==27771== Command: opt-7 -o /dev/null /dev/null ==27771== ==27771== ==27771== HEAP SUMMARY: ==27771== in use at exit: 67,640 bytes in 3 blocks ==27771== total heap usage: 3,488 allocs, 3,485 frees, 1,069,258 bytes allocated ==27771== ==27771== 67,584 bytes in 1 blocks are definitely lost in loss record 3 of 3 ==27771== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==27771== by 0x59622D3: ??? (in /usr/lib/x86_64-linux-gnu/libLLVM-7.so.1) ==27771== by 0x5909CED: llvm::EnablePrettyStackTrace() (in /usr/lib/x86_64-linux-gnu/libLLVM-7.so.1) ==27771== by 0x58F2C21: llvm::InitLLVM::InitLLVM(int&, char const**&) (in /usr/lib/x86_64-linux-gnu/libLLVM-7.so.1) ==27771== by 0x1B43F7: main (in /usr/lib/llvm-7/bin/opt) ==27771== ==27771== LEAK SUMMARY: ==27771== definitely lost: 67,584 bytes in 1 blocks ==27771== indirectly lost: 0 bytes in 0 blocks ==27771== possibly lost: 0 bytes in 0 blocks ==27771== still reachable: 56 bytes in 2 blocks ==27771== suppressed: 0 bytes in 0 blocks ==27771== Reachable blocks (those to which a pointer was found) are not shown. ==27771== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==27771== ==27771== For counts of detected and suppressed errors, rerun with: -v ==27771== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I actually tracked it down in a version compiled from source with all the debug
symbols. The leak report is very similar, except that I get the exact info on
the leaking allocation:
==20704== HEAP SUMMARY: ==20704== in use at exit: 1,020,675 bytes in 35 blocks ==20704== total heap usage: 292,536 allocs, 292,501 frees, 49,368,073 bytes allocated ==20704== ==20704== 67,584 bytes in 1 blocks are definitely lost in loss record 14 of 27 ==20704== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==20704== by 0x893D63C: safe_malloc (MemAlloc.h:27) ==20704== by 0x893D63C: CreateSigAltStack (Signals.inc:254) ==20704== by 0x893D63C: RegisterHandlers() (Signals.inc:277) ==20704== by 0x893DF9C: llvm::sys::AddSignalHandler(void (*)(void*), void*) (Signals.inc:386) ==20704== by 0x88E538D: RegisterCrashPrinter (PrettyStackTrace.cpp:180) ==20704== by 0x88E538D: llvm::EnablePrettyStackTrace() (PrettyStackTrace.cpp:188) ==20704== by 0x88CFFED: PrettyStackTraceProgram (PrettyStackTrace.h:77) ==20704== by 0x88CFFED: llvm::InitLLVM::InitLLVM(int&, char const**&) (InitLLVM.cpp:25) ==20704== by 0x41DF07: InitLLVM (InitLLVM.h:35) ==20704== by 0x41DF07: main (opt.cpp:426)
The leak shows up whenever CreateSigAltStack is called multiple times, in some
specific conditions.
The first time CreateSigAltStack is called, a new alternate signal stack
isallocated with
AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
Then the value of AltStack.ss_sp is saved into NewAltStackPointer. According
to the comments, this is a workaround to stop valgrind or asan complaining about
a leak, but it's not enough. Here's why. Whenever CreateSigAltStack is called
a second time and it reaches past the first if, a new larger alternate stack is
allocated again with
AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
But at this point, the NewAltStackPointer is overwritten, and the old
alternate signal stack is never free'd, and we don't hold a pointer to it
anymore, causing the leak.
With this fix the leak should go away. The valgrind leak report report goes away
as well.
This comment leads me to believe that the leak is quite intentional. What happens if you free the alt stack while it's being used by another signal handler?