diff --git a/Cartfile.private b/Cartfile.private index 23d7e1177..b5ed77ee1 100644 --- a/Cartfile.private +++ b/Cartfile.private @@ -1 +1 @@ -github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" +github "mattgallagher/CwlPreconditionTesting" == 1.2.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index 32a1c25f8..fbe69497d 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1 @@ -github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923" -github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5" +github "mattgallagher/CwlPreconditionTesting" "1.2.0" diff --git a/Carthage/Checkouts/CwlCatchException/Package.swift b/Carthage/Checkouts/CwlCatchException/Package.swift deleted file mode 100644 index c1e2ed837..000000000 --- a/Carthage/Checkouts/CwlCatchException/Package.swift +++ /dev/null @@ -1,9 +0,0 @@ -import PackageDescription - -let package = Package( - name: "CwlCatchException", - targets: [ - Target(name: "CwlCatchException", dependencies: ["CwlCatchExceptionSupport"]), - Target(name: "CwlCatchExceptionSupport") - ] -) diff --git a/Carthage/Checkouts/CwlCatchException/LICENSE.txt b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/LICENSE.txt similarity index 98% rename from Carthage/Checkouts/CwlCatchException/LICENSE.txt rename to Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/LICENSE.txt index ca8f5b8a3..693a2fe7d 100644 --- a/Carthage/Checkouts/CwlCatchException/LICENSE.txt +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/LICENSE.txt @@ -1,3 +1,5 @@ +ISC License + Copyright © 2017 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. Permission to use, copy, modify, and/or distribute this software for any diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Package.swift b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Package.swift new file mode 100644 index 000000000..6489eb513 --- /dev/null +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Package.swift @@ -0,0 +1,14 @@ +// swift-tools-version:4.2 +import PackageDescription + +let package = Package( + name: "CwlCatchException", + products: [ + .library(name: "CwlCatchException", type: .dynamic, targets: ["CwlCatchException"]), + ], + targets: [ + .target(name: "CwlCatchException", dependencies: [.target(name: "CwlCatchExceptionSupport")]), + .target(name: "CwlCatchExceptionSupport"), + .testTarget(name: "CwlCatchExceptionTests", dependencies: [.target(name: "CwlCatchException")]) + ] +) diff --git a/Carthage/Checkouts/CwlCatchException/README.md b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/README.md similarity index 95% rename from Carthage/Checkouts/CwlCatchException/README.md rename to Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/README.md index 0f97b031e..052d7c0e2 100644 --- a/Carthage/Checkouts/CwlCatchException/README.md +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/README.md @@ -1,7 +1,7 @@ # CwlCatchException A simple Swift wrapper around an Objective-C `@try`/`@catch` statement that selectively catches Objective-C exceptions by `NSException` subtype, rethrowing if any caught exception is not the expected subtype. -Look at [CwlCatchExceptionTests.swift](https://github.com/mattgallagher/CwlCatchException/blob/master/CwlCatchExceptionTests/CwlCatchExceptionTests.swift?ts=4) for syntax. +Look at [CwlCatchExceptionTests.swift](https://github.com/mattgallagher/CwlCatchException/blob/master/Tests/CwlCatchExceptionTests/CwlCatchExceptionTests.swift) for syntax. ## Adding to your project diff --git a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift similarity index 84% rename from Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift rename to Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift index 3e89e23b7..2cb9b2918 100644 --- a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift @@ -3,7 +3,7 @@ // CwlAssertionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -24,12 +24,12 @@ import Foundation import CwlCatchExceptionSupport #endif -private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { +private func catchReturnTypeConverter(_ type: T.Type, block: @escaping () -> Void) -> T? { return catchExceptionOfKind(type, block) as? T } extension NSException { - public static func catchException(in block: () -> Void) -> Self? { + public static func catchException(in block: @escaping () -> Void) -> Self? { return catchReturnTypeConverter(self, block: block) } } diff --git a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m similarity index 81% rename from Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m rename to Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m index 8cf414fd5..251c29cb8 100644 --- a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m @@ -3,7 +3,7 @@ // CwlAssertionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -20,10 +20,10 @@ #import "CwlCatchException.h" -#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +#if !SWIFT_PACKAGE __attribute__((visibility("hidden"))) #endif -NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) { +NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void)) { @try { inBlock(); } @catch (NSException *exception) { diff --git a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h similarity index 86% rename from Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h rename to Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h index 0c8dd878b..428d6f2a1 100644 --- a/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h +++ b/Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h @@ -3,7 +3,7 @@ // CwlCatchException // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -26,7 +26,7 @@ FOUNDATION_EXPORT double CwlCatchExceptionVersionNumber; //! Project version string for CwlCatchException. FOUNDATION_EXPORT const unsigned char CwlCatchExceptionVersionString[]; -#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE +#if !SWIFT_PACKAGE __attribute__((visibility("hidden"))) #endif -NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)); +NSException* __nullable catchExceptionOfKind(Class __nonnull type, void (^ __nonnull inBlock)(void)); diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Package.swift b/Carthage/Checkouts/CwlPreconditionTesting/Package.swift index 8792aac87..975331326 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Package.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Package.swift @@ -1,19 +1,28 @@ +// swift-tools-version:4.0 import PackageDescription let package = Package( name: "CwlPreconditionTesting", - targets: [ - Target(name: "CwlPreconditionTesting", dependencies: [ - "CwlMachBadInstructionHandler" - ]), - Target(name: "CwlMachBadInstructionHandler") + products: [ + .library(name: "CwlPreconditionTesting", type: .dynamic, targets: ["CwlPreconditionTesting", "CwlMachBadInstructionHandler"]) ], dependencies: [ - .Package(url: "https://github.com/mattgallagher/CwlCatchException.git", Version(1, 0, 2, prereleaseIdentifiers: ["beta", "3"])), + .package(url: "https://github.com/mattgallagher/CwlCatchException.git", from: "1.2.0") ], - exclude: [ - "Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", - "Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", - "Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + targets: [ + .target( + name: "CwlPreconditionTesting", + dependencies: [ + .target(name: "CwlMachBadInstructionHandler"), + .product(name: "CwlCatchException") + ], + exclude: [ + "./Mach/CwlPreconditionTesting.h", + "./Posix/CwlPreconditionTesting.h", + "./CwlCatchBadInstructionPosix.swift" + ] + ), + .target(name: "CwlMachBadInstructionHandler"), + .testTarget(name: "CwlPreconditionTestingTests", dependencies: ["CwlPreconditionTesting"]) ] ) diff --git a/Carthage/Checkouts/CwlPreconditionTesting/README.md b/Carthage/Checkouts/CwlPreconditionTesting/README.md index a42a5b5f9..259d1fe9c 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/README.md +++ b/Carthage/Checkouts/CwlPreconditionTesting/README.md @@ -18,31 +18,17 @@ Minimum requirements are iOS 8 (simulator-only) or macOS 10.9. The project inclu 1. In a subdirectory of your project's directory, run `git clone https://github.com/mattgallagher/CwlPreconditionTesting.git` 2. Drag the "CwlPreconditionTesting.xcodeproj" file from the Finder into your own project's file tree in Xcode -3. Add the "CwlPreconditionTesting.framework" from the "Products" folder of the CwlPreconditionTesting project's file tree to the "Copy Files (Frameworks)" build phases of any target that you want to include this module. -4. Drag the "CwlCatchException.framework" from the "Dependencies" group (within the CwlPreconditionTesting project's file tree) onto the same "Copy Files (Frameworks)" build phase (this item may be red but that shouldn't be a problem). - -That third step is a little tricky if you're unfamiliar with Xcode but it involves: - -a. click on your project in the file tree -b. click on the target to whih you want to add this module -c. select the "Build Phases" tab -d. if you don't already have a "Copy File" build phase with a "Destination: Frameworks", add one using the "+" button in the top left of the tab -e. click the "+" within the "Copy File (Frameworks)" phase and from the list that appears, select the "CwlPreconditionTesting.framework" (if there are multiple frameworks with the same name, look for the one that appears *above* the corresponding macOS or iOS CwlPreconditionTesting testing target). - -When building using this approach, the "FetchDependencies" target will use the Swift Package Manager to download the "CwlCatchException" project from github. The download is stored in the "Build intermediates" directory for your project. Normally, you can ignore its existence but if you get any errors from the "FetchDependencies" target, you might need to clean the build folder (Hold "Option" key while selecting "Product" → "Clean Build Folder..." from the Xcode menubar). - -You can use the "Package.swift" to manage the behavior of the Swift Package Manager or if you want to download dependencies manually (instead of using this behind-the-scenes use of the Swift package manager), you should delete the "FetchDependencies" target and replace the "CwlCatchException" targets with alternatives that build the dependencies in accordance with your manual download. +3. Add the "CwlPreconditionTesting.framework" from the "Products" folder of the CwlPreconditionTesting project's file tree to the "Copy Files (Frameworks)" build phases of any targets that you want to include this module. +4. Drag the "CwlCatchException.framework" from the "Dependencies" group (within the CwlPreconditionTesting project's file tree) onto the same "Copy Files (Frameworks)" build phase ### Swift Package Manager -Add the following to the `dependencies` array in your "Package.swift" file: - - .Package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", majorVersion: 1), - -Or, if you're using the `swift-tools-version:4.0` package manager, add the following to the `dependencies` array in your "Package.swift" file: +Assuming you're using the `swift-tools-version:4.0` package manager, add the following to the `dependencies` array in your "Package.swift" file: .package(url: "https://github.com/mattgallagher/CwlPreconditionTesting.git", majorVersion: 1) +> NOTE: even though this git repository includes its dependencies in the Dependencies folder, building via the Swift Package manager fetches and builds these dependencies independently. + ### CocoaPods Add the following lines to your target in your "Podfile": diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m index 818319672..2ab0ea5e1 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,33 +18,36 @@ // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#if defined(__x86_64__) +#ifdef __APPLE__ +#import "TargetConditionals.h" +#if TARGET_OS_OSX || TARGET_OS_IOS - #import "mach_excServer.h" - #import "CwlMachBadInstructionHandler.h" - - @protocol BadInstructionReply - +(NSNumber *)receiveReply:(NSValue *)value; - @end - - /// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state. - kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { - bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt }; - Class badInstructionClass = NSClassFromString(@"BadInstructionException"); - NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)]; - return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue]; - } - - // The mach port should be configured so that this function is never used. - kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { - assert(false); - return KERN_FAILURE; - } - - // The mach port should be configured so that this function is never used. - kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { - assert(false); - return KERN_FAILURE; - } +#import "mach_excServer.h" +#import "CwlMachBadInstructionHandler.h" + +@protocol BadInstructionReply ++(NSNumber *)receiveReply:(NSValue *)value; +@end + +/// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state. +kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { + bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt }; + Class badInstructionClass = NSClassFromString(@"BadInstructionException"); + NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)]; + return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue]; +} + +// The mach port should be configured so that this function is never used. +kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { + assert(false); + return KERN_FAILURE; +} + +// The mach port should be configured so that this function is never used. +kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { + assert(false); + return KERN_FAILURE; +} -#endif +#endif /* TARGET_OS_OSX || TARGET_OS_IOS */ +#endif /* __APPLE__ */ diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h index aef59c2cc..3fbd5a409 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -19,8 +19,14 @@ // #import + +#if TARGET_OS_OSX || TARGET_OS_IOS + #import +extern bool _swift_disableExclusivityChecking; +extern bool _swift_reportFatalErrorsToDebugger; + NS_ASSUME_NONNULL_BEGIN extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); @@ -68,3 +74,5 @@ typedef struct } bad_instruction_exception_reply_t; NS_ASSUME_NONNULL_END + +#endif diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c index 733c5644f..ccd8f84b8 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c @@ -5,13 +5,12 @@ * OPTIONS: */ -#if defined(__x86_64__) - /* Module mach_exc */ #define __MIG_check__Request__mach_exc_subsystem__ 1 -#include "mach_excServer.h" +#import "mach_excServer.h" +#if TARGET_OS_OSX || TARGET_OS_IOS #ifndef mig_internal #define mig_internal static __inline__ @@ -534,4 +533,4 @@ mig_external mig_routine_t mach_exc_server_routine return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; } -#endif +#endif /* TARGET_OS_OSX || TARGET_OS_IOS */ diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h index 52e53ae18..1f03d66c6 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h @@ -1,9 +1,14 @@ +#ifdef __APPLE__ +#import "TargetConditionals.h" +#if TARGET_OS_OSX || TARGET_OS_IOS + #ifndef _mach_exc_server_ #define _mach_exc_server_ /* Module mach_exc */ #include + #include #include #include @@ -319,3 +324,6 @@ __AfterMigServerHeader #endif /* __AfterMigServerHeader */ #endif /* _mach_exc_server_ */ + +#endif /* TARGET_OS_OSX || TARGET_OS_IOS */ +#endif /* __APPLE__ */ diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift index 91e5d4df8..d77eae3f4 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,6 +18,8 @@ // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#if os(macOS) || os(iOS) + import Foundation #if SWIFT_PACKAGE @@ -44,46 +46,44 @@ public class BadInstructionException: NSException { /// An Objective-C callable function, invoked from the `mach_exc_server` callback function `catch_mach_exception_raise_state` to push the `raiseBadInstructionException` function onto the stack. @objc(receiveReply:) public class func receiveReply(_ value: NSValue) -> NSNumber { - #if arch(x86_64) - var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil) - withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) } - - let old_state: UnsafePointer = reply.old_state! - let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt - let new_state: thread_state_t = reply.new_state! - let new_stateCnt: UnsafeMutablePointer = reply.new_stateCnt! - - // Make sure we've been given enough memory - if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT { - return NSNumber(value: KERN_INVALID_ARGUMENT) - } - - // Read the old thread state - var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee } - - // 1. Decrement the stack pointer - state.__rsp -= __uint64_t(MemoryLayout.size) - - // 2. Save the old Instruction Pointer to the stack. - if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) { - pointer.pointee = state.__rip - } else { - return NSNumber(value: KERN_INVALID_ARGUMENT) - } - - // 3. Set the Instruction Pointer to the new function's address - var f: @convention(c) () -> Void = raiseBadInstructionException - withUnsafePointer(to: &f) { - state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee } - } - - // Write the new thread state - new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state } - new_stateCnt.pointee = x86_THREAD_STATE64_COUNT - - return NSNumber(value: KERN_SUCCESS) - #else - fatalError("Unavailable for this CPU architecture") - #endif + var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil) + withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) } + + let old_state: UnsafePointer = reply.old_state! + let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt + let new_state: thread_state_t = reply.new_state! + let new_stateCnt: UnsafeMutablePointer = reply.new_stateCnt! + + // Make sure we've been given enough memory + if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT { + return NSNumber(value: KERN_INVALID_ARGUMENT) + } + + // Read the old thread state + var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee } + + // 1. Decrement the stack pointer + state.__rsp -= __uint64_t(MemoryLayout.size) + + // 2. Save the old Instruction Pointer to the stack. + if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) { + pointer.pointee = state.__rip + } else { + return NSNumber(value: KERN_INVALID_ARGUMENT) + } + + // 3. Set the Instruction Pointer to the new function's address + var f: @convention(c) () -> Void = raiseBadInstructionException + withUnsafePointer(to: &f) { + state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee } + } + + // Write the new thread state + new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state } + new_stateCnt.pointee = x86_THREAD_STATE64_COUNT + + return NSNumber(value: KERN_SUCCESS) } } + +#endif diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift index f96ec6359..51ffa9fe9 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,180 +18,192 @@ // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#if os(macOS) || os(iOS) + import Foundation +import Swift #if SWIFT_PACKAGE import CwlMachBadInstructionHandler #endif -#if arch(x86_64) - - private enum PthreadError: Error { case code(Int32) } - private enum MachExcServer: Error { case code(kern_return_t) } - - /// A quick function for converting Mach error results into Swift errors - private func kernCheck(_ f: () -> Int32) throws { - let r = f() - guard r == KERN_SUCCESS else { - throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil) - } +private enum PthreadError: Error { case code(Int32) } +private enum MachExcServer: Error { case code(kern_return_t) } + +/// A quick function for converting Mach error results into Swift errors +private func kernCheck(_ f: () -> Int32) throws { + let r = f() + guard r == KERN_SUCCESS else { + throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil) } - - extension request_mach_exception_raise_t { - mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { - return withUnsafeMutablePointer(to: &self) { p -> R in - return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in - return block(ptr) - } +} + +extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in + return block(ptr) } } } - - extension reply_mach_exception_raise_state_t { - mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { - return withUnsafeMutablePointer(to: &self) { p -> R in - return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in - return block(ptr) - } +} + +extension reply_mach_exception_raise_state_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in + return block(ptr) } } } +} + +/// A structure used to store context associated with the Mach message port +private struct MachContext { + var masks = execTypesCountTuple() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil - /// A structure used to store context associated with the Mach message port - private struct MachContext { - var masks = execTypesCountTuple() - var count: mach_msg_type_number_t = 0 - var ports = execTypesCountTuple() - var behaviors = execTypesCountTuple() - var flavors = execTypesCountTuple() - var currentExceptionPort: mach_port_t = 0 - var handlerThread: pthread_t? = nil - - static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { - return m.withMemoryRebound(to: exception_mask_t.self, capacity: 1) { masksPtr in - return c.withMemoryRebound(to: mach_msg_type_number_t.self, capacity: 1) { countPtr in - return p.withMemoryRebound(to: mach_port_t.self, capacity: 1) { portsPtr in - return b.withMemoryRebound(to: exception_behavior_t.self, capacity: 1) { behaviorsPtr in - return f.withMemoryRebound(to: thread_state_flavor_t.self, capacity: 1) { flavorsPtr in - return block(masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) - } + static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { + return m.withMemoryRebound(to: exception_mask_t.self, capacity: 1) { masksPtr in + return c.withMemoryRebound(to: mach_msg_type_number_t.self, capacity: 1) { countPtr in + return p.withMemoryRebound(to: mach_port_t.self, capacity: 1) { portsPtr in + return b.withMemoryRebound(to: exception_behavior_t.self, capacity: 1) { behaviorsPtr in + return f.withMemoryRebound(to: thread_state_flavor_t.self, capacity: 1) { flavorsPtr in + return block(masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) } } } } } - - mutating func withUnsafeMutablePointers(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { - return MachContext.internalMutablePointers(&masks, &count, &ports, &behaviors, &flavors, block) - } } - /// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away). - private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? { - let context = arg.assumingMemoryBound(to: MachContext.self).pointee - var request = request_mach_exception_raise_t() - var reply = reply_mach_exception_raise_state_t() + mutating func withUnsafeMutablePointers(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { + return MachContext.internalMutablePointers(&masks, &count, &ports, &behaviors, &flavors, block) + } +} + +/// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away). +private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? { + let context = arg.assumingMemoryBound(to: MachContext.self).pointee + var request = request_mach_exception_raise_t() + var reply = reply_mach_exception_raise_state_t() + + var handledfirstException = false + repeat { do { + // Request the next mach message from the port + request.Head.msgh_local_port = context.currentExceptionPort + request.Head.msgh_size = UInt32(MemoryLayout.size) + let requestSize = request.Head.msgh_size + try kernCheck { request.withMsgHeaderPointer { requestPtr in + mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL)) + } } - var handledfirstException = false - repeat { do { - // Request the next mach message from the port - request.Head.msgh_local_port = context.currentExceptionPort - request.Head.msgh_size = UInt32(MemoryLayout.size) - let requestSize = request.Head.msgh_size - try kernCheck { request.withMsgHeaderPointer { requestPtr in - mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL)) - } } - - // Prepare the reply structure - reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0) - reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL) - reply.Head.msgh_remote_port = request.Head.msgh_remote_port - reply.Head.msgh_size = UInt32(MemoryLayout.size) - reply.NDR = NDR_record - - if !handledfirstException { - // Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure - guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in - mach_exc_server(requestPtr, replyPtr) - } }) != 0 else { throw MachExcServer.code(reply.RetCode) } - - handledfirstException = true - } else { - // If multiple fatal errors occur, don't handle subsquent errors (let the program crash) - reply.RetCode = KERN_FAILURE - } + // Prepare the reply structure + reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0) + reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL) + reply.Head.msgh_remote_port = request.Head.msgh_remote_port + reply.Head.msgh_size = UInt32(MemoryLayout.size) + reply.NDR = NDR_record + + if !handledfirstException { + // Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure + guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in + mach_exc_server(requestPtr, replyPtr) + } }) != 0 else { throw MachExcServer.code(reply.RetCode) } - // Send the reply - let replySize = reply.Head.msgh_size - try kernCheck { reply.withMsgHeaderPointer { replyPtr in - mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL)) - } } - } catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) { - // Port was already closed before we started or closed while we were listening. - // This means the controlling thread shut down. - return nil - } catch { - // Should never be reached but this is testing code, don't try to recover, just abort - fatalError("Mach message error: \(error)") - } } while true + handledfirstException = true + } else { + // If multiple fatal errors occur, don't handle subsquent errors (let the program crash) + reply.RetCode = KERN_FAILURE + } + + // Send the reply + let replySize = reply.Head.msgh_size + try kernCheck { reply.withMsgHeaderPointer { replyPtr in + mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL)) + } } + } catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) { + // Port was already closed before we started or closed while we were listening. + // This means the controlling thread shut down. + return nil + } catch { + // Should never be reached but this is testing code, don't try to recover, just abort + fatalError("Mach message error: \(error)") + } } while true +} + +/// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil. +/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state. +/// - parameter block: a function without parameters that will be run +/// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`. +public func catchBadInstruction(in block: @escaping () -> Void) -> BadInstructionException? { + // Suppress Swift runtime's direct triggering of the debugger and exclusivity checking which crashes when we throw past it + let previousExclusivity = _swift_disableExclusivityChecking + let previousReporting = _swift_reportFatalErrorsToDebugger + _swift_disableExclusivityChecking = true + _swift_reportFatalErrorsToDebugger = false + defer { + _swift_reportFatalErrorsToDebugger = previousReporting + _swift_disableExclusivityChecking = previousExclusivity } - /// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil. - /// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state. - /// - parameter block: a function without parameters that will be run - /// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`. - public func catchBadInstruction(in block: () -> Void) -> BadInstructionException? { - var context = MachContext() - var result: BadInstructionException? = nil - do { - var handlerThread: pthread_t? = nil - defer { - // 8. Wait for the thread to terminate *if* we actually made it to the creation point - // The mach port should be destroyed *before* calling pthread_join to avoid a deadlock. - if handlerThread != nil { - pthread_join(handlerThread!, nil) - } - } - - try kernCheck { - // 1. Create the mach port - mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort) - } - defer { - // 7. Cleanup the mach port - mach_port_destroy(mach_task_self_, context.currentExceptionPort) - } - - try kernCheck { - // 2. Configure the mach port - mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND) + var context = MachContext() + var result: BadInstructionException? = nil + do { + var handlerThread: pthread_t? = nil + defer { + // 8. Wait for the thread to terminate *if* we actually made it to the creation point + // The mach port should be destroyed *before* calling pthread_join to avoid a deadlock. + if handlerThread != nil { + pthread_join(handlerThread!, nil) } + } + + try kernCheck { + // 1. Create the mach port + mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort) + } + defer { + // 7. Cleanup the mach port + mach_port_destroy(mach_task_self_, context.currentExceptionPort) + } + + try kernCheck { + // 2. Configure the mach port + mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND) + } + + let currentExceptionPtr = context.currentExceptionPort + try kernCheck { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in + // 3. Apply the mach port as the handler for this thread + thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, currentExceptionPtr, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) + } } + + defer { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in + // 6. Unapply the mach port + _ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) + } } + + try withUnsafeMutablePointer(to: &context) { c throws in + // 4. Create the thread + let e = pthread_create(&handlerThread, nil, machMessageHandler, c) + guard e == 0 else { throw PthreadError.code(e) } - let currentExceptionPtr = context.currentExceptionPort - try kernCheck { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in - // 3. Apply the mach port as the handler for this thread - thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, currentExceptionPtr, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) - } } - - defer { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in - // 6. Unapply the mach port - _ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr) - } } - - try withUnsafeMutablePointer(to: &context) { c throws in - // 4. Create the thread - let e = pthread_create(&handlerThread, nil, machMessageHandler, c) - guard e == 0 else { throw PthreadError.code(e) } - - // 5. Run the block - result = BadInstructionException.catchException(in: block) - } - } catch { - // Should never be reached but this is testing code, don't try to recover, just abort - fatalError("Mach port error: \(error)") + // 5. Run the block + result = BadInstructionException.catchException(in: block) } - return result + } catch { + // Should never be reached but this is testing code, don't try to recover, just abort + fatalError("Mach port error: \(error)") } + + return result +} #endif diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift index eb9bc199f..af6eb102a 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 8/02/2016. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,91 +18,91 @@ // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#if os(tvOS) + import Foundation -#if arch(x86_64) - - // This file is an alternative implementation to CwlCatchBadInstruction.swift that uses a SIGILL signal action and setenv/longjmp instead of a Mach exception handler and Objective-C exception raising. - // - // WARNING: - // This code is quick and dirty. It's a proof of concept for using a SIGILL handler and setjmp/longjmp where Mach exceptions and the Obj-C runtime aren't available. I ran the automated tests when I first wrote this code but I don't personally use it at all so by the time you're reading this comment, it probably broke and I didn't notice. - // Obvious limitations: - // * It doesn't work when debugging with lldb. - // * It doesn't scope correctly to the thread (it's global) - // * In violation of rules for signal handlers, it writes to the "red zone" on the stack - // * It isn't re-entrant - // * Plus all of the same caveats as the Mach exceptions version (doesn't play well with other handlers, probably leaks ARC memory, etc) - // Treat it like a loaded shotgun. Don't point it at your face. - - // This function is called from the signal handler to shut down the thread and return 1 (indicating a SIGILL was received). - private func callThreadExit() { - pthread_exit(UnsafeMutableRawPointer(bitPattern: 1)) - } - - // When called, this signal handler simulates a function call to `callThreadExit` - private func sigIllHandler(code: Int32, info: UnsafeMutablePointer<__siginfo>?, uap: UnsafeMutableRawPointer?) -> Void { - guard let context = uap?.assumingMemoryBound(to: ucontext64_t.self) else { return } +// This file is an alternative implementation to CwlCatchBadInstruction.swift that uses a SIGILL signal action and setenv/longjmp instead of a Mach exception handler and Objective-C exception raising. +// +// WARNING: +// This code is quick and dirty. It's a proof of concept for using a SIGILL handler and setjmp/longjmp where Mach exceptions and the Obj-C runtime aren't available. I ran the automated tests when I first wrote this code but I don't personally use it at all so by the time you're reading this comment, it probably broke and I didn't notice. +// Obvious limitations: +// * It doesn't work when debugging with lldb. +// * It doesn't scope correctly to the thread (it's global) +// * In violation of rules for signal handlers, it writes to the "red zone" on the stack +// * It isn't re-entrant +// * Plus all of the same caveats as the Mach exceptions version (doesn't play well with other handlers, probably leaks ARC memory, etc) +// Treat it like a loaded shotgun. Don't point it at your face. - // 1. Decrement the stack pointer - context.pointee.uc_mcontext64.pointee.__ss.__rsp -= __uint64_t(MemoryLayout.size) +// This function is called from the signal handler to shut down the thread and return 1 (indicating a SIGILL was received). +private func callThreadExit() { + pthread_exit(UnsafeMutableRawPointer(bitPattern: 1)) +} - // 2. Save the old Instruction Pointer to the stack. - let rsp = context.pointee.uc_mcontext64.pointee.__ss.__rsp - if let ump = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(rsp)) { - ump.pointee = rsp - } +// When called, this signal handler simulates a function call to `callThreadExit` +private func sigIllHandler(code: Int32, info: UnsafeMutablePointer<__siginfo>?, uap: UnsafeMutableRawPointer?) -> Void { + guard let context = uap?.assumingMemoryBound(to: ucontext64_t.self) else { return } + + // 1. Decrement the stack pointer + context.pointee.uc_mcontext64.pointee.__ss.__rsp -= __uint64_t(MemoryLayout.size) - // 3. Set the Instruction Pointer to the new function's address - var f: @convention(c) () -> Void = callThreadExit - withUnsafePointer(to: &f) { $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { ptr in - context.pointee.uc_mcontext64.pointee.__ss.__rip = ptr.pointee - } } + // 2. Save the old Instruction Pointer to the stack. + let rsp = context.pointee.uc_mcontext64.pointee.__ss.__rsp + if let ump = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(rsp)) { + ump.pointee = rsp } + + // 3. Set the Instruction Pointer to the new function's address + var f: @convention(c) () -> Void = callThreadExit + withUnsafePointer(to: &f) { $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { ptr in + context.pointee.uc_mcontext64.pointee.__ss.__rip = ptr.pointee + } } +} + +/// Without Mach exceptions or the Objective-C runtime, there's nothing to put in the exception object. It's really just a boolean – either a SIGILL was caught or not. +public class BadInstructionException { +} + +/// Run the provided block. If a POSIX SIGILL is received, handle it and return a BadInstructionException (which is just an empty object in this POSIX signal version). Otherwise return nil. +/// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a SIGILL is received, the block will be interrupted using a C `longjmp`. The risks associated with abrupt jumps apply here: most Swift functions are *not* interrupt-safe. Memory may be leaked and the program will not necessarily be left in a safe state. +/// - parameter block: a function without parameters that will be run +/// - returns: if an SIGILL is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`. +public func catchBadInstruction(block: @escaping () -> Void) -> BadInstructionException? { + // Construct the signal action + var sigActionPrev = sigaction() + let action = __sigaction_u(__sa_sigaction: sigIllHandler) + var sigActionNew = sigaction(__sigaction_u: action, sa_mask: sigset_t(), sa_flags: SA_SIGINFO) - /// Without Mach exceptions or the Objective-C runtime, there's nothing to put in the exception object. It's really just a boolean – either a SIGILL was caught or not. - public class BadInstructionException { + // Install the signal action + if sigaction(SIGILL, &sigActionNew, &sigActionPrev) != 0 { + fatalError("Sigaction error: \(errno)") } - /// Run the provided block. If a POSIX SIGILL is received, handle it and return a BadInstructionException (which is just an empty object in this POSIX signal version). Otherwise return nil. - /// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a SIGILL is received, the block will be interrupted using a C `longjmp`. The risks associated with abrupt jumps apply here: most Swift functions are *not* interrupt-safe. Memory may be leaked and the program will not necessarily be left in a safe state. - /// - parameter block: a function without parameters that will be run - /// - returns: if an SIGILL is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`. - public func catchBadInstruction(block: @escaping () -> Void) -> BadInstructionException? { - // Construct the signal action - var sigActionPrev = sigaction() - let action = __sigaction_u(__sa_sigaction: sigIllHandler) - var sigActionNew = sigaction(__sigaction_u: action, sa_mask: sigset_t(), sa_flags: SA_SIGINFO) - - // Install the signal action - if sigaction(SIGILL, &sigActionNew, &sigActionPrev) != 0 { + defer { + // Restore the previous signal action + if sigaction(SIGILL, &sigActionPrev, nil) != 0 { fatalError("Sigaction error: \(errno)") } - - defer { - // Restore the previous signal action - if sigaction(SIGILL, &sigActionPrev, nil) != 0 { - fatalError("Sigaction error: \(errno)") - } - } + } - var b = block - let caught: Bool = withUnsafeMutablePointer(to: &b) { blockPtr in - // Run the block on its own thread - var handlerThread: pthread_t? = nil - let e = pthread_create(&handlerThread, nil, { arg in - (arg.assumingMemoryBound(to: (() -> Void).self).pointee)() - return nil - }, blockPtr) - precondition(e == 0, "Unable to create thread") + var b = block + let caught: Bool = withUnsafeMutablePointer(to: &b) { blockPtr in + // Run the block on its own thread + var handlerThread: pthread_t? = nil + let e = pthread_create(&handlerThread, nil, { arg in + (arg.assumingMemoryBound(to: (() -> Void).self).pointee)() + return nil + }, blockPtr) + precondition(e == 0, "Unable to create thread") - // Wait for completion and get the result. It will be either `nil` or bitPattern 1 - var rawResult: UnsafeMutableRawPointer? = nil - let e2 = pthread_join(handlerThread!, &rawResult) - precondition(e2 == 0, "Thread join failed") - return Int(bitPattern: rawResult) != 0 - } - - return caught ? BadInstructionException() : nil + // Wait for completion and get the result. It will be either `nil` or bitPattern 1 + var rawResult: UnsafeMutableRawPointer? = nil + let e2 = pthread_join(handlerThread!, &rawResult) + precondition(e2 == 0, "Thread join failed") + return Int(bitPattern: rawResult) != 0 } + return caught ? BadInstructionException() : nil +} + #endif diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift index 8d99d5ebe..78f571704 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -18,38 +18,38 @@ // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#if os(macOS) || os(iOS) + import Darwin -#if arch(x86_64) - - // From /usr/include/mach/message.h - // #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */ - // #define MACH_MSGH_BITS_REMOTE(bits) \ - // ((bits) & MACH_MSGH_BITS_REMOTE_MASK) - // #define MACH_MSGH_BITS(remote, local) /* legacy */ \ - // ((remote) | ((local) << 8)) - public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20 - public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) } - public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) } - - // From /usr/include/mach/exception_types.h - // #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */ - // #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION) - public let EXC_BAD_INSTRUCTION: UInt32 = 2 - public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION - - // From /usr/include/mach/i386/thread_status.h - // #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ - // ( sizeof (x86_thread_state64_t) / sizeof (int) )) - public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size) - - public let EXC_TYPES_COUNT = 14 - public struct execTypesCountTuple { - // From /usr/include/mach/i386/exception.h - // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */ - public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - public init() { - } +// From /usr/include/mach/message.h +// #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */ +// #define MACH_MSGH_BITS_REMOTE(bits) \ +// ((bits) & MACH_MSGH_BITS_REMOTE_MASK) +// #define MACH_MSGH_BITS(remote, local) /* legacy */ \ +// ((remote) | ((local) << 8)) +public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20 +public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) } +public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) } + +// From /usr/include/mach/exception_types.h +// #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */ +// #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION) +public let EXC_BAD_INSTRUCTION: UInt32 = 2 +public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION + +// From /usr/include/mach/i386/thread_status.h +// #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ +// ( sizeof (x86_thread_state64_t) / sizeof (int) )) +public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size) + +public let EXC_TYPES_COUNT = 14 +public struct execTypesCountTuple { + // From /usr/include/mach/i386/exception.h + // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */ + public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + public init() { } +} #endif diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h deleted file mode 100644 index 4e28f9514..000000000 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// CwlPreconditionTesting.h -// CwlPreconditionTesting -// -// Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -extern bool _swift_reportFatalErrorsToDebugger; - -//! Project version number for CwlUtils. -FOUNDATION_EXPORT double CwlPreconditionTesting_POSIXVersionNumber; - -//! Project version string for CwlUtils. -FOUNDATION_EXPORT const unsigned char CwlAssertingTesting_POSIXVersionString[]; diff --git a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/include/CwlPreconditionTesting.h similarity index 81% rename from Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h rename to Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/include/CwlPreconditionTesting.h index 7c50da11b..93a0e610c 100644 --- a/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h +++ b/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/include/CwlPreconditionTesting.h @@ -3,7 +3,7 @@ // CwlPreconditionTesting // // Created by Matt Gallagher on 2016/01/10. -// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -20,13 +20,16 @@ #import -extern bool _swift_reportFatalErrorsToDebugger; - //! Project version number for CwlUtils. FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber; //! Project version string for CwlUtils. FOUNDATION_EXPORT const unsigned char CwlAssertingTestingVersionString[]; -#include "CwlMachBadInstructionHandler.h" -#include "CwlCatchException.h" +#import "CwlMachBadInstructionHandler.h" + +#if TARGET_OS_OSX || TARGET_OS_IOS + #import "CwlCatchException.h" +#elif !TARGET_OS_TV + #error Unsupported platform. +#endif diff --git a/Nimble.podspec b/Nimble.podspec index f3b103d89..7005f90bf 100644 --- a/Nimble.podspec +++ b/Nimble.podspec @@ -16,26 +16,24 @@ Pod::Spec.new do |s| s.source_files = [ "Sources/**/*.{swift,h,m,c}", - "Carthage/Checkouts/CwlCatchException/Sources/**/*.{swift,h,m,c}", + "Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/**/*.{swift,h,m,c}", "Carthage/Checkouts/CwlPreconditionTesting/Sources/**/*.{swift,h,m,c}", ] s.osx.exclude_files = [ "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", - "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", ] s.ios.exclude_files = [ "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", - "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Posix/CwlPreconditionTesting_POSIX.h", ] s.tvos.exclude_files = [ "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift", "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift", "Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift", - "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", - "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", - "Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", + "Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift", + "Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m", + "Carthage/Checkouts/CwlPreconditionTesting/Dependencies/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h", ] s.exclude_files = "Sources/Nimble/Adapters/NonObjectiveC/*.swift" diff --git a/Nimble.xcodeproj/project.pbxproj b/Nimble.xcodeproj/project.pbxproj index 1685c6114..5179f22f5 100644 --- a/Nimble.xcodeproj/project.pbxproj +++ b/Nimble.xcodeproj/project.pbxproj @@ -380,6 +380,9 @@ CD79C9B51D2CC848004B6F9A /* ObjCUserDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */; }; CD79C9B61D2CC848004B6F9A /* ObjCAllPassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */; }; CD79C9B71D2CC848004B6F9A /* ObjCSatisfyAnyOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */; }; + CD8D21BD2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8D21BC2322BFC300C3996F /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CD8D21BE2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8D21BC2322BFC300C3996F /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CD8D21BF2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8D21BC2322BFC300C3996F /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; CDD80B831F2030790002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; CDD80B841F20307A0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; @@ -395,8 +398,6 @@ CDFB6A3C1F7E082500AD8CC7 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */; }; CDFB6A3F1F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */; }; CDFB6A401F7E082500AD8CC7 /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */; }; - CDFB6A431F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CDFB6A441F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; CDFB6A471F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; }; CDFB6A481F7E082500AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; }; CDFB6A491F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -404,9 +405,8 @@ CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */; }; CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */; }; CDFB6A4F1F7E084600AD8CC7 /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */; }; - CDFB6A501F7E085600AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; }; + CDFB6A501F7E085600AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */; }; - CDFB6A521F7E089F00AD8CC7 /* CwlPreconditionTesting_POSIX.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA9E8C821A414BB9002633C2 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; DA9E8C831A414BB9002633C2 /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9E8C811A414BB9002633C2 /* DSL+Wait.swift */; }; DD72EC641A93874A002F7651 /* AllPassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD72EC631A93874A002F7651 /* AllPassTest.swift */; }; @@ -622,6 +622,7 @@ B20058C020E92C7500C1264D /* ElementsEqual.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqual.swift; sourceTree = ""; }; B20058C420E92CE400C1264D /* ElementsEqualTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqualTest.swift; sourceTree = ""; }; CD037212207DCC580047AF28 /* XCTestManifests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = ""; }; + CD8D21BC2322BFC300C3996F /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = ""; }; @@ -629,8 +630,6 @@ CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPosix.swift; sourceTree = ""; }; CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; - CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; - CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting_POSIX.h; sourceTree = ""; }; CDFB6A341F7E082400AD8CC7 /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; CDFB6A361F7E082400AD8CC7 /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; CDFB6A371F7E082400AD8CC7 /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; @@ -940,6 +939,14 @@ path = objc; sourceTree = ""; }; + CD8D21BB2322BFC300C3996F /* include */ = { + isa = PBXGroup; + children = ( + CD8D21BC2322BFC300C3996F /* CwlPreconditionTesting.h */, + ); + path = include; + sourceTree = ""; + }; CDFB69521F7E06E600AD8CC7 /* Carthage-Checkouts */ = { isa = PBXGroup; children = ( @@ -957,7 +964,7 @@ CDFB6A1F1F7E07C600AD8CC7 /* CwlCatchExceptionSupport */, ); name = CwlCatchException; - path = CwlCatchException/Sources; + path = CwlPreconditionTesting/Dependencies/CwlCatchException/Sources; sourceTree = ""; }; CDFB69741F7E076F00AD8CC7 /* CwlPreconditionTesting */ = { @@ -998,32 +1005,15 @@ CDFB6A291F7E082400AD8CC7 /* CwlPreconditionTesting */ = { isa = PBXGroup; children = ( + CD8D21BB2322BFC300C3996F /* include */, CDFB6A2A1F7E082400AD8CC7 /* CwlBadInstructionException.swift */, CDFB6A2B1F7E082400AD8CC7 /* CwlCatchBadInstruction.swift */, CDFB6A2C1F7E082400AD8CC7 /* CwlCatchBadInstructionPosix.swift */, CDFB6A2D1F7E082400AD8CC7 /* CwlDarwinDefinitions.swift */, - CDFB6A2F1F7E082400AD8CC7 /* Mach */, - CDFB6A311F7E082400AD8CC7 /* Posix */, ); path = CwlPreconditionTesting; sourceTree = ""; }; - CDFB6A2F1F7E082400AD8CC7 /* Mach */ = { - isa = PBXGroup; - children = ( - CDFB6A301F7E082400AD8CC7 /* CwlPreconditionTesting.h */, - ); - path = Mach; - sourceTree = ""; - }; - CDFB6A311F7E082400AD8CC7 /* Posix */ = { - isa = PBXGroup; - children = ( - CDFB6A321F7E082400AD8CC7 /* CwlPreconditionTesting_POSIX.h */, - ); - path = Posix; - sourceTree = ""; - }; CDFB6A331F7E082400AD8CC7 /* CwlMachBadInstructionHandler */ = { isa = PBXGroup; children = ( @@ -1050,9 +1040,9 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + CD8D21BE2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */, CDFB6A4A1F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */, CDFB6A281F7E07C700AD8CC7 /* CwlCatchException.h in Headers */, - CDFB6A441F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */, 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */, 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */, 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */, @@ -1064,8 +1054,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - CDFB6A521F7E089F00AD8CC7 /* CwlPreconditionTesting_POSIX.h in Headers */, 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */, + CD8D21BF2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */, 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */, 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */, CDFB6A501F7E085600AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */, @@ -1077,10 +1067,10 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + CD8D21BD2322BFC300C3996F /* CwlPreconditionTesting.h in Headers */, CDFB6A491F7E082500AD8CC7 /* CwlMachBadInstructionHandler.h in Headers */, CDFB6A271F7E07C700AD8CC7 /* CwlCatchException.h in Headers */, 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */, - CDFB6A431F7E082500AD8CC7 /* CwlPreconditionTesting.h in Headers */, 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */, 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */, 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */, diff --git a/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Sources/Nimble/Adapters/NimbleXCTestHandler.swift index 719bf44d2..cd3b47608 100644 --- a/Sources/Nimble/Adapters/NimbleXCTestHandler.swift +++ b/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -45,7 +45,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler { private var stashed_swift_reportFatalErrorsToDebugger: Bool = false @objc func testCaseWillStart(_ testCase: XCTestCase) { - #if swift(>=3.2) + #if swift(>=3.2) && !os(tvOS) stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger _swift_reportFatalErrorsToDebugger = false #endif @@ -56,7 +56,7 @@ class NimbleXCTestUnavailableHandler: AssertionHandler { @objc func testCaseDidFinish(_ testCase: XCTestCase) { currentTestCase = nil - #if swift(>=3.2) + #if swift(>=3.2) && !os(tvOS) _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger #endif } diff --git a/Sources/Nimble/Nimble.h b/Sources/Nimble/Nimble.h index 2bbc69368..bd45c5dde 100644 --- a/Sources/Nimble/Nimble.h +++ b/Sources/Nimble/Nimble.h @@ -3,11 +3,7 @@ #import "NMBStringify.h" #import "DSL.h" -#if TARGET_OS_TV - #import "CwlPreconditionTesting_POSIX.h" -#else - #import "CwlPreconditionTesting.h" -#endif +#import "CwlPreconditionTesting.h" FOUNDATION_EXPORT double NimbleVersionNumber; FOUNDATION_EXPORT const unsigned char NimbleVersionString[];