[PATCH] D59005: Fix memory leak in CreateSigAltStack
Pietro Fezzardi via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 5 16:01:26 PST 2019
fez created this revision.
Herald added subscribers: llvm-commits, jdoerfert, hiraditya.
Herald added a reviewer: jfb.
Herald added a project: LLVM.
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.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D59005
Files:
llvm/lib/Support/Unix/Signals.inc
Index: llvm/lib/Support/Unix/Signals.inc
===================================================================
--- llvm/lib/Support/Unix/Signals.inc
+++ llvm/lib/Support/Unix/Signals.inc
@@ -252,10 +252,13 @@
stack_t AltStack = {};
AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
- NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
AltStack.ss_size = AltStackSize;
- if (sigaltstack(&AltStack, &OldAltStack) != 0)
+ if (sigaltstack(&AltStack, &OldAltStack) != 0) {
free(AltStack.ss_sp);
+ } else {
+ free(NewAltStackPointer);
+ NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
+ }
}
#else
static void CreateSigAltStack() {}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D59005.189416.patch
Type: text/x-patch
Size: 714 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190306/185d206f/attachment.bin>
More information about the llvm-commits
mailing list