Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift Compiler crashes when using a weak self inside a callback #78366

Open
tapthaker opened this issue Dec 26, 2024 · 0 comments
Open

Swift Compiler crashes when using a weak self inside a callback #78366

tapthaker opened this issue Dec 26, 2024 · 0 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. crash Bug: A crash, i.e., an abnormal termination of software triage needed This issue needs more specific labels

Comments

@tapthaker
Copy link
Contributor

tapthaker commented Dec 26, 2024

Description

The crash happens if I try to use the self? inside the callback

Reproduction

import CoreServices
import Foundation

enum FileWatchError: Error {
    case unableToCreateEventStream
    case unableToStartEventStream
}

enum FileChangeType: Sendable {
    case modified
    case created
    case deleted
    
    static func from(flags: FSEventStreamEventFlags) -> FileChangeType {
        if flags & UInt32(kFSEventStreamEventFlagItemModified) != 0 {
            return .modified
        }
        
        if flags & UInt32(kFSEventStreamEventFlagItemCreated) != 0 {
            return .created
        }
        
        if flags & UInt32(kFSEventStreamEventFlagItemRemoved) != 0 {
            return .deleted
        }
        
        fatalError("Unknown file change type")
    }
}

struct FileChange: Sendable {
    let filePath: String
    let changeType: FileChangeType
    
    static func fromFSChanges(files: [String], flagsArray: [FSEventStreamEventFlags]) -> [FileChange] {
        var filesChanges: [FileChange] = []
        for (index, path) in files.enumerated() {
            let flags = flagsArray[index]
            let pathChangeType = FileChangeType.from(flags: flags)
            filesChanges.append(FileChange(filePath: path, changeType: pathChangeType))
        }
        return filesChanges
    }
    
}

actor FileWatcher {
    
    let watchPaths: [String]
    var filesChanges: [FileChange] = []
    
    init (watchPaths: [String]) {
        self.watchPaths = watchPaths
    }
    
    
    func start() throws {
        let pathsToWatch = ["/path/to/directory"]
        let latency: CFTimeInterval = 1.0
        
        let callback: FSEventStreamCallback = { [weak self] (streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIds) in
            let files = unsafeBitCast(eventPaths, to: NSArray.self) as! [String]
            let flagsArray = Array(UnsafeBufferPointer(start: eventFlags, count: numEvents))
            let currentFileChanges = FileChange.fromFSChanges(files: files, flagsArray: flagsArray)
            Task {
                // The swift compiler crashes due the the line below
                // You can avoid the crash by commenting it
                await self?.addFileChanges(currentFileChanges)
            }
        }
        
        var context = FSEventStreamContext()
        let stream = FSEventStreamCreate(
            kCFAllocatorDefault,
            callback,
            &context,
            pathsToWatch as CFArray,
            FSEventsGetCurrentEventId(),
            latency,
            UInt32(kFSEventStreamCreateFlagFileEvents)
        )
        
        guard let stream else {
            throw FileWatchError.unableToCreateEventStream
        }
        
        FSEventStreamSetDispatchQueue(stream, DispatchQueue.global(qos: .default))
        let success = FSEventStreamStart(stream)
        
        if !success {
           throw FileWatchError.unableToCreateEventStream
        }
    }
    
    func addFileChanges(_ fileChanges: [FileChange]) {
        filesChanges.append(contentsOf: fileChanges)
    }
    
}

Stack dump

1.	Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
2.	Compiling with the current language version
3.	While evaluating request ExecuteSILPipelineRequest(Run pipelines { Mandatory Diagnostic Passes + Enabling Optimization Passes } on SIL for TerrariumLib)
4.	While running pass #593 SILFunctionTransform "TransferNonSendable" on SILFunction "@$s12TerrariumLib11FileWatcherC5startyyKF".
 for 'start()' (at /Users/tapanth/Uber/Terrarium/TerrariumLib/FileWatch.swift:63:5)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x00000001079a2a9c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x00000001079a0cf0 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x00000001079a3068 SignalHandler(int) + 292
3  libsystem_platform.dylib 0x000000019c96ae04 _sigtramp + 56
4  libsystem_pthread.dylib  0x000000019c933f70 pthread_kill + 288
5  libsystem_c.dylib        0x000000019c840908 abort + 128
6  swift-frontend           0x00000001033881c4 swift::Partition::merge(swift::PartitionPrimitives::Element, swift::PartitionPrimitives::Element, bool) + 248
7  swift-frontend           0x0000000102f0e258 swift::RegionAnalysisFunctionInfo::RegionAnalysisFunctionInfo(swift::SILFunction*, swift::PostOrderFunctionInfo*) + 14308
8  swift-frontend           0x0000000102f11190 swift::RegionAnalysis::newFunctionAnalysis(swift::SILFunction*) + 56
9  swift-frontend           0x00000001031582c0 (anonymous namespace)::TransferNonSendable::run() + 324
10 swift-frontend           0x000000010318db74 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) + 3448
11 swift-frontend           0x000000010318a158 swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 11968
12 swift-frontend           0x00000001031c36a4 swift::SimpleRequest<swift::ExecuteSILPipelineRequest, std::__1::tuple<> (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 56
13 swift-frontend           0x00000001031a7008 swift::ExecuteSILPipelineRequest::OutputType swift::Evaluator::getResultUncached<swift::ExecuteSILPipelineRequest, swift::ExecuteSILPipelineRequest::OutputType swift::evaluateOrFatal<swift::ExecuteSILPipelineRequest>(swift::Evaluator&, swift::ExecuteSILPipelineRequest)::'lambda'()>(swift::ExecuteSILPipelineRequest const&, swift::ExecuteSILPipelineRequest::OutputType swift::evaluateOrFatal<swift::ExecuteSILPipelineRequest>(swift::Evaluator&, swift::ExecuteSILPipelineRequest)::'lambda'()) + 412
14 swift-frontend           0x00000001031a9784 swift::runSILDiagnosticPasses(swift::SILModule&) + 612
15 swift-frontend           0x00000001027200e4 swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 84
16 swift-frontend           0x000000010234a9c4 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1376
17 swift-frontend           0x0000000102349bd0 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 984
18 swift-frontend           0x000000010234ce88 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1684
19 swift-frontend           0x000000010234bbb4 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3572
20 swift-frontend           0x00000001022d2a5c swift::mainEntry(int, char const**) + 3680
21 dyld                     0x000000019c5b4274 start + 2840


### Expected behavior

The compilation should succeed

### Environment

swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
Target: arm64-apple-macosx15.0


### Additional information

_No response_
@tapthaker tapthaker added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. crash Bug: A crash, i.e., an abnormal termination of software triage needed This issue needs more specific labels labels Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. crash Bug: A crash, i.e., an abnormal termination of software triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

1 participant