On 12.09.2019 10:09, Robert Elz wrote: > The right change to make however is to teach the santitsers (all of them) > that exiting (via exit() or a return from main()) frees everything, This proposal is practically equivalent of disabling leak detection at all and removes the whole purpose. Leak detection works simply by scanning memory (TLS, stacks, heap) for pointers to allocations. If there is no longer a reference, than there is a leak. I have not investigated where are the sh(1) leaks, but the pointers are still accessible in memory. There are few tests failing in regression test-suite and they related to pointers that are on the stack. There is apparently a bug in calculating the range of used/valid stack region somewhere or something that has this red-herring effect. (I would like to see it fixed, but I am supposed to do other things now and cannot focus on it.) On 12.09.2019 10:55, Jason Thorpe wrote:> >> On Sep 12, 2019, at 11:09 AM, Robert Elz <kre%munnari.OZ.AU@localhost> wrote: >> >> To me it seems apparent that the sanatiser is detecting the local variable >> in main() go out of scope when main() returns, and so the value it contains >> (the pointer to the allocated memory) is lost, and so it is determined that >> there is a leak. For any other function that would often be true, but for >> main() it never is. > > It seems obvious that the sanitizer should special-case main(). > > -- thorpej > In sanitizers we cannot overload or do anything special with main() (such as replace it with our own copy). If this would be the case, it would be simpler to perform some operations in other sanitizers. main() is the same entity as any regular fun(). Unless we decorate it with some attributes in .c code, it is not distinguishable. On 12.09.2019 07:39, Simon Burge wrote:> for the free-just-before-exit cases? Leak detection is performed just before the exit. Technically it is performed from atexit(3) handler that is expected to be the last one to be executed. We need to perform this phase in that moment as we need to fire other atexit handlers, destructors etc. main() is not really privileged here. At least with LSan there is an option to perform the end-of-process check on demand with __lsan_do_leak_check(), it will disable the atexit(3) handler later on. But it is not much different to adding workarounds for 1 type of leak detecting software. On 12.09.2019 10:09, Robert Elz wrote:> If this is what is happening, it would seem that a relatively cost free > fix, instead of calling free() Globals are treated specially in sanitizers as sanitizers generate constructors and destructors to keep the track of them. LSan on NetBSD is still distanced from being as good as the Linux equivalent so it's not a perfect example of presenting how LSan behaves., I wouldn't assume that globals can store freely pointers. Even if this is the case today, it would be fixed in future. On 12.09.2019 10:09, Robert Elz wrote:> | There is a cost of calling a dummy function _suppress_leak(), but it is > | probably negligible. > > No, it isn't. The way you have described it, that function needs to be > called for every block of allocated memory that has been allocated, and is > never going to be freed. That means either calling this function immediately > after all (or much) memory is allocated, even if it turns out that memory is > later freed, as often the code does not know what allocations will be released > and which will still be active when the program terminates. Or every time > the program is about to exit, it needs to traverse all of its data structures > calling this function on all memory that had perviously been allocated. > Potentially thousands of these dummy function calls. I have benchmarked in the past that we execute for true(1) or similar applications at least 1 million instructions on CPU. $ ./singlestepper true Total count: 1639915 $ ./singlestepper echo Total count: 1039124 Calling one 1 dummy function in libc in comparison to that is negligible. We are talking here about simple programs that are expected to get some measurable optimization by skipping free(3) calls. Such as sh(1) or ps(1). In all other cases I consider this style of programming as buggy. If there are thousands of leaked memory objects than it is not just simple optimization, but really wrong style of programming. One example of that is ATF, it randomly picks one set of pointers to free before exit, and skips others leaking the memory. It is bug. As I have stated originally, we could remove free(3) from almost every basesystem program and not many would notice. There is even a C compiler that performs only allocations and never frees the memory. It is still a correct UNIX application, regardless of taking like 2GB for building a hello world application.
Attachment:
signature.asc
Description: OpenPGP digital signature