如何忽略 nim 中的 "broken pipe" 异常
How to ignore "broken pipe" exception in nim
我正在编写一个 CLI 程序,当我执行像 program | head
这样的二进制文件时,我得到:
Error: unhandled exception: errno: 32 `Broken pipe` [IOError]
我想消除这个异常并尝试添加:
import posix
signal(SIG_PIPE, SIG_IGN)
在我的主要程序中,但这并没有消除错误。该程序使用 threadspool
,调用另一个过程来分析输入行池。 (我不知道这是否与问题相关)
更新:
- 这是我的非工作程序:https://pastebin.com/aQaRgfXR(使用
responses.add(spawn parseArray(readspool, mergeOptions))
生成的线程)
- 这是完整的错误:
/Users/telatina/miniconda3/nim/lib/pure/concurrency/threadpool.nim(377) slave
/Users/telatina/git/nim-stuff/orf/src/porfidus.nim(307) parseArrayWrapper
/Users/telatina/git/nim-stuff/orf/src/porfidus.nim(247) parseArray
/Users/telatina/miniconda3/nim/lib/system/io.nim(155) checkErr
/Users/telatina/miniconda3/nim/lib/system/io.nim(138) raiseEIO
Error: unhandled exception: errno: 0 `Undefined error: 0` [IOError]
使用 nim 1.2.6 和以下程序(不要认为它是好的风格):
import os, posix, threadpool
signal(SIG_PIPE, SIG_IGN)
proc noise =
for i in 0 ..< int(1e6):
echo i
threadpool.spawn noise()
threadpool.spawn noise()
threadpool.sync()
当 运行 如下所示时,它明显忽略了 EPIPE 并且显然是从多个线程打印(因为看到了两个 60s,然后在两个线程到达循环末尾时出现延迟):
$ ./brokenpipe |grep -m2 -F 60
60
60
注释掉 signal
调用后,最后一条命令引发错误:
$ ./brokenpipe |grep -m2 -F 60
60
60
Traceback (most recent call last)
/home/jfondren/.choosenim/toolchains/nim-1.2.6/lib/pure/concurrency/threadpool.nim(377) slave
/home/jfondren/nim/learn/brokenpipe.nim(8) noiseWrapper
/home/jfondren/nim/learn/brokenpipe.nim(6) noise
/home/jfondren/.choosenim/toolchains/nim-1.2.6/lib/system/io.nim(648) echoBinSafe
SIGPIPE: Pipe closed.
因此您的解决方案似乎有效,您确实需要一个它未解决的问题的最小示例。
基于@julian-fondren 的回答和您的代码,我能够复制您的错误。
import os, posix, threadpool
signal(SIG_PIPE, SIG_IGN)
proc noise =
for i in 0 ..< int(1e6):
stdout.write($i & '\n')
threadpool.spawn noise()
threadpool.spawn noise()
threadpool.sync()
对于跟随者。
您也在代码中使用了 stdout.write
,may throw an IO Exception
由于您使用 SIG_IGN
线程在接收到 SIG_PIPE
时不会停止 运行,而是继续在损坏的管道上调用 stdout.write
,从而引发异常。
为了解决这个问题,我找到了三个选项
处理异常
这是最通用的解决方案,适用于您的代码因“错误:未处理的异常”而崩溃的任何情况
to handle an exception in Nim 使用 try
和 except
.
stdout.write($i & '\n')
变为
try:
stdout.write($i & '\n')
except IOError:
#handle it by ending the program
quit()
#or ignore it with
#discard
- 处理信号
在我的机器上使用
SIG_DFL
会导致线程静默终止,从而按照您的意愿运行,但这取决于平台。所以你也可以注册你自己的信号处理程序(抱歉丑陋的造型)
#signal(SIG_PIPE,SIG_DFL)
signal(SIG_PIPE,cast[typeof(SIG_IGN)](proc(signal:cint) =
stderr.write("handled sigpipe\n")
quit()
))
- 就用echo
echo
,不像 stdout.write
不会抛出异常,所以对于这种情况,这可能是最简单的修复方法
我正在编写一个 CLI 程序,当我执行像 program | head
这样的二进制文件时,我得到:
Error: unhandled exception: errno: 32 `Broken pipe` [IOError]
我想消除这个异常并尝试添加:
import posix
signal(SIG_PIPE, SIG_IGN)
在我的主要程序中,但这并没有消除错误。该程序使用 threadspool
,调用另一个过程来分析输入行池。 (我不知道这是否与问题相关)
更新:
- 这是我的非工作程序:https://pastebin.com/aQaRgfXR(使用
responses.add(spawn parseArray(readspool, mergeOptions))
生成的线程) - 这是完整的错误:
/Users/telatina/miniconda3/nim/lib/pure/concurrency/threadpool.nim(377) slave
/Users/telatina/git/nim-stuff/orf/src/porfidus.nim(307) parseArrayWrapper
/Users/telatina/git/nim-stuff/orf/src/porfidus.nim(247) parseArray
/Users/telatina/miniconda3/nim/lib/system/io.nim(155) checkErr
/Users/telatina/miniconda3/nim/lib/system/io.nim(138) raiseEIO
Error: unhandled exception: errno: 0 `Undefined error: 0` [IOError]
使用 nim 1.2.6 和以下程序(不要认为它是好的风格):
import os, posix, threadpool
signal(SIG_PIPE, SIG_IGN)
proc noise =
for i in 0 ..< int(1e6):
echo i
threadpool.spawn noise()
threadpool.spawn noise()
threadpool.sync()
当 运行 如下所示时,它明显忽略了 EPIPE 并且显然是从多个线程打印(因为看到了两个 60s,然后在两个线程到达循环末尾时出现延迟):
$ ./brokenpipe |grep -m2 -F 60
60
60
注释掉 signal
调用后,最后一条命令引发错误:
$ ./brokenpipe |grep -m2 -F 60
60
60
Traceback (most recent call last)
/home/jfondren/.choosenim/toolchains/nim-1.2.6/lib/pure/concurrency/threadpool.nim(377) slave
/home/jfondren/nim/learn/brokenpipe.nim(8) noiseWrapper
/home/jfondren/nim/learn/brokenpipe.nim(6) noise
/home/jfondren/.choosenim/toolchains/nim-1.2.6/lib/system/io.nim(648) echoBinSafe
SIGPIPE: Pipe closed.
因此您的解决方案似乎有效,您确实需要一个它未解决的问题的最小示例。
基于@julian-fondren 的回答和您的代码,我能够复制您的错误。
import os, posix, threadpool
signal(SIG_PIPE, SIG_IGN)
proc noise =
for i in 0 ..< int(1e6):
stdout.write($i & '\n')
threadpool.spawn noise()
threadpool.spawn noise()
threadpool.sync()
对于跟随者。
您也在代码中使用了 stdout.write
,may throw an IO Exception
由于您使用 SIG_IGN
线程在接收到 SIG_PIPE
时不会停止 运行,而是继续在损坏的管道上调用 stdout.write
,从而引发异常。
为了解决这个问题,我找到了三个选项
处理异常
这是最通用的解决方案,适用于您的代码因“错误:未处理的异常”而崩溃的任何情况
to handle an exception in Nim 使用
try
和except
.
stdout.write($i & '\n')
变为
try:
stdout.write($i & '\n')
except IOError:
#handle it by ending the program
quit()
#or ignore it with
#discard
- 处理信号
在我的机器上使用
SIG_DFL
会导致线程静默终止,从而按照您的意愿运行,但这取决于平台。所以你也可以注册你自己的信号处理程序(抱歉丑陋的造型)
#signal(SIG_PIPE,SIG_DFL)
signal(SIG_PIPE,cast[typeof(SIG_IGN)](proc(signal:cint) =
stderr.write("handled sigpipe\n")
quit()
))
- 就用echo
echo
,不像stdout.write
不会抛出异常,所以对于这种情况,这可能是最简单的修复方法