Skip to content

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

Open
@tapthaker

Description

@tapthaker

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    SILaccepts invalidBug: Accepts invalidbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c interopFeature: Interoperability with CclosuresFeature: closurescompilerThe Swift compiler itselfcrashBug: A crash, i.e., an abnormal termination of softwareexpressionsFeature: expressionsswift 6.0

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions