Skip to content

Commit

Permalink
fix: Concurrency crash for Swift 6 (#4512)
Browse files Browse the repository at this point in the history
Swift 6 introduce some concurrency checks to avoid race conditions, but objc does not have this features.
We need to annotate of callbacks so swift knows how it will be used.
  • Loading branch information
brustolin authored Nov 11, 2024
1 parent 489fbb8 commit 4509e9c
Show file tree
Hide file tree
Showing 17 changed files with 855 additions and 182 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ui-tests-critical.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- run: ./scripts/ci-select-xcode.sh 16
- run: ./scripts/ci-select-xcode.sh "16.0"
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
Expand Down
21 changes: 20 additions & 1 deletion .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}}

# GitHub Actions sometimes fail to launch the UI tests. Therefore we retry
- name: Run Fastlane
run: for i in {1..2}; do fastlane ui_tests_ios_swiftui device:"${{matrix.device}}" && break ; done
Expand Down Expand Up @@ -110,3 +110,22 @@ jobs:
path: |
~/Library/Logs/scan/*.log
./fastlane/test_output/**
ui-tests-swift6:
name: UI Tests for iOS-Swift6 Simulator
runs-on: macos-14

steps:
- uses: actions/checkout@v4
- run: ./scripts/ci-select-xcode.sh "16.0"
- name: Run Fastlane
run: fastlane ui_tests_ios_swift6

- name: Archiving Raw Test Logs
uses: actions/upload-artifact@v4
if: ${{ failure() || cancelled() }}
with:
name: raw-ios-swift-test-output-${{matrix.xcode}}-${{matrix.device}}
path: |
~/Library/Logs/scan/*.log
./fastlane/test_output/**
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Fixes

- Keep PropagationContext when cloning scope (#4518)
- Concurrency crash with Swift 6 (#4512)

## 8.40.1

Expand Down
638 changes: 466 additions & 172 deletions Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D8F71A4B2CDD03B900334022"
BuildableName = "iOS-Swift6.app"
BlueprintName = "iOS-Swift6"
ReferencedContainer = "container:iOS-Swift.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D8F71A6A2CDD03BB00334022"
BuildableName = "iOS-Swift6UITests.xctest"
BlueprintName = "iOS-Swift6UITests"
ReferencedContainer = "container:iOS-Swift.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D8F610A12CDCBCF900A77147"
BuildableName = "iOS-Swift6Tests.xctest"
BlueprintName = "iOS-Swift6Tests"
ReferencedContainer = "container:iOS-Swift.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D8F71A4B2CDD03B900334022"
BuildableName = "iOS-Swift6.app"
BlueprintName = "iOS-Swift6"
ReferencedContainer = "container:iOS-Swift.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D8F71A4B2CDD03B900334022"
BuildableName = "iOS-Swift6.app"
BlueprintName = "iOS-Swift6"
ReferencedContainer = "container:iOS-Swift.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
48 changes: 48 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Sentry
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

func startSentry() {
SentrySDK.start(configureOptions: { options in
options.dsn = "https://[email protected]/5428557"
options.beforeSend = { event in
print("Sentry: beforeSend called")
return event
}
options.beforeSendSpan = { span in
print("Sentry: beforeSendSpan called")
return span
}
options.beforeCaptureScreenshot = { _ in
print("Sentry: beforeCaptureScreenshot called")
return true
}
options.beforeCaptureViewHierarchy = { _ in
print("Sentry: beforeCaptureViewHierarchy called")
return true
}
options.attachScreenshot = true
options.attachViewHierarchy = true
options.debug = true
options.sampleRate = 1
options.tracesSampleRate = 1
})

}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
startSentry()
return true
}

// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
25 changes: 25 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
47 changes: 47 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="iOS_Swift6" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="q7a-UR-VaD">
<rect key="frame" x="133" y="421" width="127" height="35"/>
<accessibility key="accessibilityConfiguration" identifier="btError"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" title="Capture Error"/>
<connections>
<action selector="buttonTapped:" destination="BYZ-38-t0r" eventType="touchUpInside" id="1ma-mq-zKe"/>
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="q7a-UR-VaD" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="Byz-jG-rg1"/>
<constraint firstItem="q7a-UR-VaD" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="vr4-Vs-njb"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="138" y="5"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
25 changes: 25 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
24 changes: 24 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
}

func sceneDidDisconnect(_ scene: UIScene) {
}

func sceneDidBecomeActive(_ scene: UIScene) {
}

func sceneWillResignActive(_ scene: UIScene) {
}

func sceneWillEnterForeground(_ scene: UIScene) {
}

func sceneDidEnterBackground(_ scene: UIScene) {
}
}
10 changes: 10 additions & 0 deletions Samples/iOS-Swift/iOS-Swift6/ViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Sentry
import UIKit

class ViewController: UIViewController {
@IBAction func buttonTapped(_ sender: Any) {
DispatchQueue.global(qos: .utility).async {
SentrySDK.capture(error: NSError(domain: "Swift 6 Test", code: -1))
}
}
}
Loading

0 comments on commit 4509e9c

Please sign in to comment.