Closed hassila closed 2 years ago
See also https://github.com/apple/swift/issues/58482 for a reproducer.
Based on the stack trace, this looks to me like it's probably a leak in the Swift runtime. @mikeash @al45tair thoughts?
Looks like this is a side table being leaked. I’d guess this is a false positive due to the lead sanitizer not recognizing whatever weird bit stuffing we’re doing with the pointer to the side table.
Yes, LSan works by scanning memory, so it isn't going to find pointers where we've stuffed extra bits of data into them. The reason this works on macOS is that the tools there do understand Swift's internal data structures and know what to do to turn bit patterns into pointers there.
Ok, thanks - but where are those diffs? I thought the tool chains on both platforms share source from llvm with the tsan support? Just trying to understand- it'd be great to have tsan/asan working for Linux too for swift on server in heterogeneous environments.
Perhaps this is then not a bug for xctest but for the swift project?
Sorry, perhaps I wasn't clear. On macOS, people tend to use leaks
rather than LSan to find memory leaks. leaks
knows about all kinds of macOS specific things, including the weird bit packing we do in the Swift and ObjC language runtimes. I don't know whether anyone has made any attempt to teach LSan any of that; if they have, it may just be that it's only turned on when running on macOS.
Whether that's a Swift bug per se, I'm not so sure (LSan belongs to clang). It isn't an XCTest bug though.
But lsan has been suggested as the go-to tool for Linux / Swift - e.g.
https://forums.swift.org/t/test-for-memory-leaks-in-ci/36526/5
https://github.com/swift-server/guides/blob/main/docs/memory-leaks-and-usage.md
https://github.com/apple/swift-issues/issues/6848
So it seems expected from different Apple engineers that it should work on Linux?
Cc: @gottesmm @weissi @lukasa
It's the right tool, certainly. If it doesn't presently work for Swift, we should make it work, IMO. The thing to do is to file a bug report against either Swift or Clang (or both); the right people will see it and sort out who does what.
@hassila valgrind/heaptrack/LSan are the best tools we have on non-Darwin platforms today. Unfortunately, the leak checking isn't reliable and cannot easily be made to be reliable. The problem is what @mikeash referred to as 'bit stuffing' but even constructions like
class A {}
class B {}
enum Something {
case a(A)
case b(B)
}
which are absolutely ubiquitous in Swift may cause trouble. Why? Because Swift is smart enough to use the spare bits in pointers for things like enum tags. In other words, it uses 'bit stuffing' without the programmer doing anything particularly smart:
8> MemoryLayout<Something>.size
$R0: Int = 8
These constructions already throw off tools that rely on grooming the heap for live pointers. Sure, they can also mask away the unused bits but sometimes the unused bits being 0 is relied on to even recognise pointers.
Where it most prominently fails is the manual bit stuffing that's used by String
and elsewhere.
So how does leaks
/heap
on macOS work? leaks
has much more runtime & programming language information and really understands the heap (as opposed to the tools mentioned above which see the heap just as a see of pointers/malloc blocks that they perform some reachability analysis on -- without any information about the language/runtime). That's why it can give you the correct type information for allocated/leaked blocks and its analyses are actually really good. Sadly, we currently don't have anything comparable on Linux yet.
Don't get me wrong, valgrind/heaptrack/LSan still provide value on Linux but they may raise some false positives. So they'll show genuine leaks but they'll also show some allocations as leaks that aren't actually leaked (still reachable but through some 'bit stuffed' pointers).
And definitely +1 on @al45tair, we should file bugs when we see these tools misreporting. These issues can be improved, it might not necessarily be easy but it's definitely possible.
Thanks for all the replies, but it seems that the fact that it doesn't signal a leak on macOS would point to that LSan is aware of the bit stuffing? Perhaps it's platform specific as suggested.
So I will file issues on Swift/Clang then as a next step, thanks.
it seems that the fact that it doesn't signal a leak on macOS
Does it not? If so, that's interesting and might mean the the fix is more straightforward.
it seems that the fact that it doesn't signal a leak on macOS
Does it not? If so, that's interesting and might mean the the fix is more straightforward.
No it doesn't, we've set up CI on both platforms and we only get the (false) positives on Linux. Granted, we don't have a huge data set, but it seems to be the case with reasonable certainty.
Running with the 5.6 swift toolchain and related artefacts - this is reproduced on Ubuntu - running
gives the following from xctest:
The test is just empty (after having stripped it out piece by piece to nail down the leaker):
On macOS with the xctest running there with Xcode 13.3, I don't get any leak.