Skip to content

Commit e057172

Browse files
authored
Make _swift_willThrow atomic (#62349)
* Make _swift_willThrow atomic
1 parent ed01f20 commit e057172

File tree

5 files changed

+47
-81
lines changed

5 files changed

+47
-81
lines changed

Diff for: stdlib/private/StdlibUnittest/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
4646
StdlibCoreExtras.swift
4747
StringConvertible.swift
4848
StringTestHelpers.swift
49-
SymbolLookup.swift
5049
TestHelpers.swift
5150
TypeIndexed.swift
5251

Diff for: stdlib/private/StdlibUnittest/SymbolLookup.swift

-55
This file was deleted.

Diff for: stdlib/public/runtime/ErrorObjectCommon.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@
2424

2525
using namespace swift;
2626

27-
void (*swift::_swift_willThrow)(SwiftError *error);
27+
std::atomic<void (*)(SwiftError *error)> swift::_swift_willThrow;
28+
29+
void swift::_swift_setWillThrowHandler(void (* handler)(SwiftError *error)) {
30+
_swift_willThrow.store(handler, std::memory_order_release);
31+
}
2832

2933
/// Breakpoint hook for debuggers, and calls _swift_willThrow if set.
3034
SWIFT_CC(swift) void
3135
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
3236
SWIFT_ERROR_RESULT SwiftError **error) {
3337
// Cheap check to bail out early, since we expect there to be no callbacks
3438
// the vast majority of the time.
35-
if (SWIFT_LIKELY(!_swift_willThrow))
36-
return;
37-
_swift_willThrow(*error);
39+
auto handler = _swift_willThrow.load(std::memory_order_acquire);
40+
if (SWIFT_UNLIKELY(handler)) {
41+
(* handler)(*error);
42+
}
3843
}

Diff for: stdlib/public/runtime/ErrorObjectTestSupport.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,20 @@
1717
#ifndef SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
1818
#define SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
1919

20+
#include <atomic>
21+
2022
namespace swift {
2123

22-
SWIFT_RUNTIME_EXPORT void (*_swift_willThrow)(SwiftError *error);
24+
#if defined(__cplusplus)
25+
SWIFT_RUNTIME_EXPORT std::atomic<void (*)(SwiftError *error)> _swift_willThrow;
26+
#endif
2327

28+
/// Set the value of @c _swift_willThrow atomically.
29+
///
30+
/// This function is present for use by the standard library's test suite only.
31+
SWIFT_CC(swift)
32+
SWIFT_RUNTIME_STDLIB_SPI
33+
void _swift_setWillThrowHandler(void (* handler)(SwiftError *error));
2434
}
2535

2636
#endif

Diff for: test/stdlib/Error.swift

+27-20
Original file line numberDiff line numberDiff line change
@@ -219,28 +219,35 @@ func throwJazzHands() throws {
219219
throw SillyError.JazzHands
220220
}
221221

222-
ErrorTests.test("willThrow") {
223-
if #available(SwiftStdlib 5.2, *) {
224-
// Error isn't allowed in a @convention(c) function when ObjC interop is
225-
// not available, so pass it through an OpaquePointer.
226-
typealias WillThrow = @convention(c) (OpaquePointer) -> Void
227-
let willThrow = pointerToSwiftCoreSymbol(name: "_swift_willThrow")!
228-
let callback: WillThrow = {
229-
errors.append(unsafeBitCast($0, to: Error.self))
230-
}
231-
willThrow.storeBytes(of: callback, as: WillThrow.self)
232-
expectTrue(errors.isEmpty)
233-
do {
234-
try throwNegativeOne()
235-
} catch {}
236-
expectEqual(UnsignedError.self, type(of: errors.last!))
222+
// Error isn't allowed in a @convention(c) function when ObjC interop is
223+
// not available, so pass it through an UnsafeRawPointer.
224+
@available(SwiftStdlib 5.8, *)
225+
@_silgen_name("_swift_setWillThrowHandler")
226+
func setWillThrowHandler(
227+
_ handler: (@convention(c) (UnsafeRawPointer) -> Void)?
228+
)
237229

238-
do {
239-
try throwJazzHands()
240-
} catch {}
241-
expectEqual(2, errors.count)
242-
expectEqual(SillyError.self, type(of: errors.last!))
230+
ErrorTests.test("willThrow") {
231+
guard #available(SwiftStdlib 5.8, *) else {
232+
return
243233
}
234+
setWillThrowHandler {
235+
errors.append(unsafeBitCast($0, to: Error.self))
236+
}
237+
defer {
238+
setWillThrowHandler(nil)
239+
}
240+
expectTrue(errors.isEmpty)
241+
do {
242+
try throwNegativeOne()
243+
} catch {}
244+
expectEqual(UnsignedError.self, type(of: errors.last!))
245+
246+
do {
247+
try throwJazzHands()
248+
} catch {}
249+
expectEqual(2, errors.count)
250+
expectEqual(SillyError.self, type(of: errors.last!))
244251
}
245252
246253
runAllTests()

0 commit comments

Comments
 (0)