[swift-corelibs-dev] NSTask and try!
Bouke Haarsma
bouke at haarsma.eu
Sat May 14 03:33:29 CDT 2016
The failing testcase is
TestNSTask.test_pipe_stdout_and_stderr_same_pipe. The call to
posix_spawn returns an error code 9 (EBADF).
In order to avoid code repetition I've wrapped all posix calls with a
throwing status code check;
private func posix(_ code: Int32) throws {
switch code {
case 0: return
default: throw NSError(domain: NSPOSIXErrorDomain, code: Int(code),
userInfo: nil)
}
}
However this produces the not-so-helpful error dump on OSX:
Test Case 'TestNSTask.test_pipe_stdout_and_stderr_same_pipe' started at
10:20:59.741
fatal error: 'try!' expression unexpectedly raised an error: <NSError:
0x0000600000067c40>: file
/Users/buildnode/jenkins/workspace/oss-swift-package-osx/swift/stdlib/public/core/ErrorType.swift,
line 53
On 2016-05-13 21:07:59 +0000, Tony Parker via swift-corelibs-dev said:
>
>> On May 13, 2016, at 1:05 PM, James Lee <james at jelee.co.uk> wrote:
>>
>> Cheers for the clarification. I started assuming there may be a reason
>> when changing the guard let on the launch args to use the
>> InvalidArgumentException.
>>
>> Could this be a position where we may need os checking to cover the
>> regression for the moment. It seems odd that the test would pass in CI
>> when an error is thrown with a try! but fail on OSX
> Task is certainly one of the cases where the underlying stuff that
> we’re abstracting is significantly different, so I’m not too surprised.
>
> We should try to get something in place so we’re not failing on OS X in
> the short term for sure.
>
> - Tony
>
>> Sent from my iPhone
>>
>>> On 13 May 2016, at 20:48, Tony Parker <anthony.parker at apple.com> wrote:
>>>
>>> Hi James,
>>>
>>>> On May 13, 2016, at 12:25 PM, James Lee via swift-corelibs-dev
>>>> <swift-corelibs-dev at swift.org> wrote:
>>>>
>>>> Following on from a previous discussion with Tests failing on OSX. I
>>>> have been looking into the failures. It seems that one of the earliest
>>>> failures is due to an error from a try! within NSTask.launch(). This
>>>> came in with this commit:
>>>> https://github.com/apple/swift-corelibs-foundation/commit/4c6f04cfcad3d4b06688558021595d06751fc66a
>>>>
>>>>
>>>> Going by the docs for Foundation - The launch function apparently
>>>> "Raises an NSInvalidArgumentException if the launch path has not been
>>>> set or is invalid or if it fails to create a process."
>>>>
>>>> https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTask_Class/#//apple_ref/occ/instm/NSTask/launch
>>>>
>>>>
>>>> My question is, should this be built into the Swift Foundation API? The
>>>> documentation for Swift doesn't state that the launch function throws.
>>>>
>>>> With the test that is failing expecting an error, it feels more Swift-y
>>>> to have any errors throw explicitly, rather than looking at what the
>>>> lower level fills the data with.
>>>>
>>>> But before jumping into doing this, I would rather put it out there and
>>>> see what the community feels about this?
>>>
>>> Unfortunately the ‘throws’ syntax in Swift often causes a mixup between
>>> two different things, because it flipped the terminology from what all
>>> of our documentation and header comments use.
>>>
>>> 1. Cocoa uses exceptions (@throw in ObjC) to indicate programmer errors
>>> and they are generally not intended to be recoverable. Example:
>>> passing nil where not expected, passing an invalid argument, failing to
>>> meet a precondition of an API.
>>> 2. Cocoa uses NSError ** to indicate runtime errors that are
>>> recoverable or at least presentable to user. Example: out of disk
>>> space, name of file already exists.
>>>
>>> The ‘throws’ syntax in Swift is actually for case #2, not #1. In Swift,
>>> #1 is fatalError or preconditionFailure. #2 is ‘throw Error’.
While API compatibility should be the fore-most goal here, I feel like
there's room for improvement here for the API overlays. While in ObjC
one has the ability to recover from NSInvalidArgumentException, on
Swift this would trap.
>>>
>>> In the case of NSTask, when the documentation says “raises an
>>> NSInvalidArgumentException” (#1) then in Swift, that should translate
>>> to fatalError or preconditionFailure.
As a resort; I propose to change the error wrapper (see
https://github.com/apple/swift-corelibs-foundation/pull/362):
private func posix(_ code: Int32) {
switch code {
case 0: return
case EBADF: fatalError("POSIX command failed with error: \(code) -- EBADF")
default: fatalError("POSIX command failed with error: \(code)")
}
}
Which would produce the following –more helpful– error on OSX:
Test Case 'TestNSTask.test_pipe_stdout_and_stderr_same_pipe' started at
10:13:55.584
fatal error: POSIX command failed with error: 9 -- EBADF: file
<somedir>/swift-corelibs-foundation/Foundation/NSTask.swift, line 424
>>>
>>> Hope this helps,
>>> - Tony
>>>
>>>> Cheers
>>>>
>>>> James
>>>> _______________________________________________
>>>> swift-corelibs-dev mailing list
>>>> swift-corelibs-dev at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
>>>
>>
>
> _______________________________________________
> swift-corelibs-dev mailing list
> swift-corelibs-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20160514/93e56a5b/attachment.html>
More information about the swift-corelibs-dev
mailing list