-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Closed
Labels
bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.A deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labelsThis issue needs more specific labels
Description
Description
A de-initing ErrorObject with a weak reference and a side table will end up calling swift_unownedRelease which asserts on non-class objects.
//
// Note: This shortcut is NOT an optimization.
// Some allocations passed to swift_deallocObject() are not compatible
// with swift_unownedRelease() because they do not have ClassMetadata.
if (object->refCounts.canBeFreedNow()) {
// object state DEINITING -> DEAD
swift_slowDealloc(object, allocatedSize, allocatedAlignMask);
} else {
// object state DEINITING -> DEINITED
swift_unownedRelease(object);
}
The ErrorObject has a side table and is on the doDecrementSlow slow path, object->refCounts.canBeFreedNow() will always return false:
DEINITING with side table
Weak variable load returns nil.
Weak variable store stores nil.
canBeFreedNow() is always false, so it never transitions directly to DEAD.
Everything else is the same as DEINITING.
The control flow is examplePackageTests.xctestexample() -> swift_release -> doDecrementSlow -> _swift_release_dealloc -> _destroyErrorObject -> swift_deallocObject -> swift_deallocObjectImpl -> swift_unownedRelease
Backtrace at assert:
frame #5: 0x00007ffff5e2b71b libc.so.6`__assert_fail_base(fmt="%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion="object->metadata->isClassObject()", file="/home/ryan_mansfield/swift/swift/stdlib/public/runtime/HeapObject.cpp", line=559, function="void swift::swift_unownedRelease(HeapObject *)") at assert.c:94:3
frame #6: 0x00007ffff5e3ce96 libc.so.6`__GI___assert_fail(assertion="object->metadata->isClassObject()", file="/home/ryan_mansfield/swift/swift/stdlib/public/runtime/HeapObject.cpp", line=559, function="void swift::swift_unownedRelease(HeapObject *)") at assert.c:103:3
frame #7: 0x00007ffff7c0c183 libswiftCore.so`swift_deallocObjectImpl(swift::HeapObject*, unsigned long, unsigned long, bool) [inlined] swift_unownedRelease(object=0x00007fffe4009050) at HeapObject.cpp:559:3
frame #8: 0x00007ffff7c0c164 libswiftCore.so`swift_deallocObjectImpl(object=0x00007fffe4009050, allocatedSize=48, allocatedAlignMask=7, isDeiniting=<unavailable>) at HeapObject.cpp:986:5
frame #9: 0x00007ffff7c0bbe0 libswiftCore.so`_swift_release_dealloc(object=0x00007fffe4009050) at HeapObject.cpp:759:3
* frame #10: 0x00007ffff7c0c9c3 libswiftCore.so`bool swift::RefCounts<swift::SideTableRefCountBits>::doDecrementSlow<(swift::PerformDeinit)1>(this=<unavailable>, oldbits=<unavailable>, dec=<unavailable>) at RefCount.h:1052:7
frame #11: 0x0000555555588578 examplePackageTests.xctest`example() at exampleTests.swift:24:1
frame #12: 0x0000555555587841 examplePackageTests.xctest`$s12exampleTests0A04TestfMp_7__localfMu_ #1 @Sendable (_0=nil) in $s12exampleTests0A04TestfMp_16Z4872561636a65b3fMu_@Sendable () at @__swiftmacro_12exampleTests0A04TestfMp_.swift:4:100
frame #13: 0x000055555558766c examplePackageTests.xctest`$s12exampleTests0A04TestfMp_16Z4872561636a65b3fMu_@Sendable () at @__swiftmacro_12exampleTests0A04TestfMp_.swift:6:13
frame #14: 0x00007ffff62adb0c libTesting.so`closure #1 in closure #1 in closure #1 in static Runner._runTestCase(_:within:) [inlined] closure #1 @Sendable (testCase=<unavailable>) async throws -> () in closure #1 @Sendable () async throws -> () in closure #1 () async throws -> () in closure #1 () async -> () in static Testing.Runner._runTestCase(_: Testing.Test.Case, within: Testing.Runner.Plan.Step) async throws -> () at Runner.swift:373:32 [opt]
frame #15: 0x00007ffff62adb0c libTesting.so`closure #1 in closure #1 in closure #1 in static Runner._runTestCase(_:within:) [inlined] static Testing.Runner._applyScopingTraits(test=<unavailable>, testCase=<unavailable>, body=<unavailable>) async throws -> ()) async throws -> () at Runner.swift:91:24 [opt]
frame #16: 0x00007ffff62adb0c libTesting.so`closure #1 in closure #1 in closure #1 in static Runner._runTestCase(, step=<unavailable>, testCase=Testing.Test.Case @ 0x0000507000178a40) at Runner.swift:372:21 [opt]
(lldb) p object->metadata->dump()
TargetMetadata.
Kind: ErrorObject.
Value Witnesses: 0x7ffff7df7640.
(lldb) p object->dump()
HeapObject: 0x7fffe4009050
HeapMetadata Pointer: 0x7ffff7df7098.
Strong Ref Count: 1.
Unowned Ref Count: 1.
Weak Ref Count: 2.
Uses Native Retain: Not a class. N/A.
RefCount Side Table: 0x7fffe8002fe0.
Is Deiniting: true.
Reproduction
This can be observed by throwing an ErrorObject from a swift test
import Testing
@testable import example
public struct myStringError: Equatable, Error {
public let description: String
public init(_ description: String) {
self.description = description
}
}
func functhrows() throws {
throw myStringError("error")
}
@Test func example() {
do {
#expect(throws: (any Error).self) {
try functhrows()
}
}
}
$ swift test
Building for debugging...
[1/1] Write swift-version-7CABD121BF667B0B.txt
Build complete! (0.14s)
Test Suite 'All tests' started at 2025-04-28 13:49:19.454
Test Suite 'debug.xctest' started at 2025-04-28 13:49:19.456
Test Suite 'debug.xctest' passed at 2025-04-28 13:49:19.456
Executed 0 tests, with 0 failures (0 unexpected) in 0.0 (0.0) seconds
Test Suite 'All tests' passed at 2025-04-28 13:49:19.456
Executed 0 tests, with 0 failures (0 unexpected) in 0.0 (0.0) seconds
◇ Test run started.
↳ Testing Library Version: 6.3-dev (6023a5fb9a6ff4f)
↳ Target Platform: x86_64-unknown-linux-gnu
◇ Test example() started.
examplePackageTests.xctest: /home/ryan_mansfield/swift/swift/stdlib/public/runtime/HeapObject.cpp:559: void swift::swift_unownedRelease(HeapObject *): Assertion `object->metadata->isClassObject()' failed.
*** Signal 6: Backtracing from 0x7ff941a9b9fc... done ***
*** Program crashed: Aborted at 0x3a07e1530000a66b ***
Platform: x86_64 Linux (Ubuntu 22.04 LTS)
Thread 0 "examplePackageT":
0 0x00007ff941a4780a sigsuspend + 74 in libc.so.6
...
Thread 1:
0 0x00007ff941a96117 __futex_abstimed_wait_cancelable64 + 231 in libc.so.6
...
Thread 2 crashed:
0 0x00007ff941a9b9fc pthread_kill@@GLIBC_2.34 + 300 in libc.so.6
...
Thread 3:
0 0x00007ff941b2ae2e epoll_wait + 94 in libc.so.6
...
Thread 4:
0 0x00007ff941a96117 __futex_abstimed_wait_cancelable64 + 231 in libc.so.6
...
Thread 5:
0 0x00007ff941a96117 __futex_abstimed_wait_cancelable64 + 231 in libc.so.6
...
Registers:
rax 0x0000000000000000 0
rdx 0x00007ff93ea7c640 40 c6 a7 3e f9 7f 00 00 40 16 00 38 f9 7f 00 00 @Ƨ>ù···@··8ù···
rcx 0x00007ff941a9b9fc 41 89 c5 41 f7 dd 3d 00 f0 ff ff b8 00 00 00 00 A·ÅA÷Ý=·ðÿÿ¸····
rbx 0x0000000000000006 6
rsi 0x000000000000a66b 42603
rdi 0x000000000000a66f 42607
rbp 0x000000000000a66f 42607
rsp 0x00007ff93ea7b710 dc 9e 01 30 f9 7f 00 00 b0 9d 01 30 f9 7f 00 00 Ü··0ù···°··0ù···
r8 0x00007ff93ea7b7e0 20 00 00 00 00 00 00 00 a0 06 c2 41 f9 7f 00 00 ······· ·ÂAù···
r9 0x0000000000000000 0
r10 0x0000000000000008 8
r11 0x0000000000000246 582
r12 0x0000000000000006 6
r13 0x0000000000000016 22
r14 0x00007ff943a29344 6f 62 6a 65 63 74 2d 3e 6d 65 74 61 64 61 74 61 object->metadata
r15 0x0000000000000007 7
rip 0x00007ff941a9b9fc 41 89 c5 41 f7 dd 3d 00 f0 ff ff b8 00 00 00 00 A·ÅA÷Ý=·ðÿÿ¸····
rflags 0x0000000000000246 ZF PF
cs 0x0033 fs 0x0000 gs 0x0000
Images (22 omitted):
0x00007ff941a05000–0x00007ff941bc1341 cd410b710f0f094c6832edd95931006d883af48e libc.so.6 /usr/lib/x86_64-linux-gnu/libc.so.6
Backtrace took 0.01s
Expected behavior
No assertion. The test does not assert on macOS.
Environment
Happens on
$ swiftc -v
Swift version 6.2-dev (LLVM 0dc2e2691f4f2cd, Swift 5d36643)
Target: x86_64-unknown-linux-gnu
Additional information
No response
Metadata
Metadata
Assignees
Labels
bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.A deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labelsThis issue needs more specific labels