【发布时间】:2016-03-15 10:52:09
【问题描述】:
我正在尝试为 Swift 中的简单命令行批处理脚本同步读取 URL 的内容。为了简单起见,我使用 cURL - 我知道如果必须,我可以使用 NSURLSession。我也在用swift build 在 OSX 上使用开源版本的 Swift 构建它。
问题在于,在某些 URL 上,如果标准输出已被重定向到管道,则 NSTask 永远不会终止。
// This will hang, and when terminated with Ctrl-C reports "(23) Failed writing body"
import Foundation
let task = NSTask()
let pipe = NSPipe()
task.launchPath = "/usr/bin/curl"
task.arguments = ["http://trove.nla.gov.au/newspaper/page/21704647"]
task.standardOutput = pipe
task.launch()
task.waitUntilExit()
但是,如果您移除管道或更改 URL,则任务会成功。
// This will succeed - no pipe
import Foundation
let task = NSTask()
task.launchPath = "/usr/bin/curl"
task.arguments = ["http://trove.nla.gov.au/newspaper/page/21704647"]
task.launch()
task.waitUntilExit()
// This will succeed - different URL
import Foundation
let task = NSTask()
let pipe = NSPipe()
task.launchPath = "/usr/bin/curl"
task.arguments = ["http://trove.nla.gov.au/newspaper/page/21704646"]
task.standardOutput = pipe
task.launch()
task2.waitUntilExit()
从终端直接使用 curl 运行任何示例都会成功,因此当从特定 URL(和其他一些 URL)检索时,以及存在管道时,与 NSTask 的交互存在一些问题,这会导致 cURL失败。
【问题讨论】:
-
愚蠢的问题;但是您确定要在这里使用“let”而不是“var”。如果任务产生输出,它是否会被分配回变量本身?
-
对于管道,您的意思是?输出被传递到可以从中读取它的管道。输出不会替换 NSPipe 实例本身。
-
好的,但是我在这段代码中没有看到“var”,只有“let”;没有任何东西被传回给任何东西?
-
当然,这是一个最小的例子。在生产代码中,标准输出的内容被解析并返回给调用上下文。但这个例子足以说明问题——task3挂了,而task1和task2成功完成。
-
托比;确定您遇到了某种竞争条件或锁定问题,您是否尝试过将每个进程移动到自己的线程?