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

[SR-1941] Dispatch object creation can return nil despite non-nil type annotations #738

Open
swift-ci opened this issue Jun 30, 2016 · 2 comments

Comments

@swift-ci
Copy link

Previous ID SR-1941
Radar None
Original Reporter miken (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s libdispatch
Labels Bug
Assignee mww (JIRA)
Priority Medium

md5: d1490ba04e755f83c340b8874532c6bf

Issue Description:

Attempting to create a dispatch source or I/O channel is a fallible operation. In Swift 2.2 the functions used for creating them are annotated as returning implicitly-unwrapped optionals, and nil is returned when creation fails. This can be checked for and handled appropriately.

In Swift 2.3 and 3.0 the functions/initializers are annotated as returning non-nil values, but nil can still be returned. This can be reproduced by providing invalid parameters.

The code below will run successfully under Swift 2.2, but will crash at runtime under 2.3 and 3.0 despite the lack of any forced or implicit unwrapping.

#if swift(>=3.0)
    
    let channel = DispatchIO(type: .stream, path: "../bad.path", oflag: O_RDONLY, mode: S_IRUSR, queue: .main) { (error) in
        print(error)
    }
    print(channel) // Crash
    
    let source = DispatchSource.signal(signal: Int32.min)
    print(source) // Crash
    
#elseif swift(>=2.3)
    
    let channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, "../bad.path", O_RDONLY, S_IRUSR, dispatch_get_main_queue()) { (error) in
        print(error)
    }
    print(channel) // Crash
    
    let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, UInt.max, 0, dispatch_get_main_queue())
    print(source) // Crash
    
#else
    
    let channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, "../bad.path", O_RDONLY, S_IRUSR, dispatch_get_main_queue()) { (error) in
        print(error)
    }
    print(channel ?? "Nil") // Nil
    
    let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, UInt.max, 0, dispatch_get_main_queue())
    print(source ?? "Nil") // Nil
    
#endif
@belkadan
Copy link

cc das (JIRA User)

Workaround: immediately assign the result of the initializer into an optional.

@swift-ci
Copy link
Author

Comment by Daniel A. Steffen (JIRA)

This was intentional and follows the rules established by Foundation for nullability annotation of return values.

The only time source object creation can return nil is on programmer error by passing bad input arguments that are non-sensical or contradictory (like in your example with a nonsensical signal number). It never returns nil for conditions that cannot be controlled by the programmer locally at the call site.

Similarly for dispatch_io, path-based creation requires an absolute path and so when that is not the case we treat that input as programmer error. The only other case treated this way is a bad channel type (c.f. source code, all these cases are expressed as DISPATCH_BAD_INPUT)

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from swiftlang/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants