<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">MOTIVATION:<div class=""><br class=""></div><div class="">In Swift 3, NSTask was renamed to Process, making it the de facto API for spawning external tasks in Swift applications. Unfortunately, NSTask uses Objective-C exceptions to report runtime errors in spawning external tasks, which cannot be caught from Swift code. This means that if something goes wrong, like the file unexpectedly not existing at the launch path, or the current user not having permission to launch it or something, there’s no way to handle that gracefully other than crashing the whole program.</div><div class=""><br class=""></div><div class="">PROPOSED SOLUTION:</div><div class=""><br class=""></div><div class="">Rename Process back to NSTask, and provide a Swift-native Process class for Foundation in Swift 4 that mimics NSTask's interface, but provides a throwing version of the ‘launch’ method:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">open</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">class</span><span style="font-variant-ligatures: no-common-ligatures" class=""> Process</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="color: rgb(0, 132, 0);" class="">// ...</span></div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(186, 45, 162);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">open</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">func</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> launch() throws</span></div></div><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="color: rgb(186, 45, 162);"><br class=""></span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"> <span style="color: rgb(0, 132, 0);" class="">// ...</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">}</span></div></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">Almost all of the work for this is already done in the swift-corelibs-Foundation project. The only NSUnimplemented() calls are in the suspend(), resume(), interrupt(), and terminate() methods, which do not seem difficult to implement. Beyond that, there are three fatalError() calls in the source file, which would need to be replaced with throws. There would also, of course, need to be “throws” annotations on the declarations for launch() and posix(), and “try” keywords added to the four calls to posix(). All told, not a large undertaking.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">For backward source compatibility, the existing, non-throwing APIs could be provided as well, but deprecated. These could simply call the throwing APIs and either call fatalError() or throw an NSException when an error is caught.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">I cannot think of too many instances where NSTask objects need to be passed around, so bridging to Objective-C is probably not a major concern.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">IMPACT ON EXISTING CODE:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Since the new class would have the same name and public API as the existing Process (NSTask) class, this would not break source compatibility. It would break binary compatibility, which makes it a consideration for Swift 4.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Charles</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div></body></html>