[英]Getting a pipe status in Go
我無法在Go(1.5)中獲得管道狀態。
在編寫由mkfifo
創建的管道時,我嘗試獲取此輸出管道的狀態:
Write
返回狀態EPIPE
Write
返回狀態EPIPE
和signal.Ignore
在SIGPIPE上忽略(以防萬一) signal.Notify
在SIGPIPE上signal.Notify
我知道:
EPIPE
kill -13
,信號處理程序稱為:“收到信號:管道損壞” ctrl-c
讀取器時,未調用信號處理程序,並且我的程序退出,並顯示以下輸出:“ signal:broken pipe” 請您指出我的錯誤嗎?
// tee.go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
sys "golang.org/x/sys/unix"
)
// wait for a signal and print it
func handleSignal(csig chan os.Signal) {
for {
fmt.Println("Wait signal")
s := <-csig
fmt.Println("Got signal:", s)
}
}
func main() {
csig := make(chan os.Signal, 1)
// `kill -13` outputs "Got signal: broken pipe" => ok
signal.Notify(csig, sys.SIGPIPE)
// OR disable the previous `Notify` just to be sure ?
// maybe it will help to get the EPIPE error status on `Write` ?
//signal.Ignore(sys.SIGPIPE)
go handleSignal(csig)
// open previously created named pipe (`mkfifo /tmp/test`)
pipe, _ := os.OpenFile("/tmp/test", os.O_WRONLY, 0)
for {
_, err := pipe.Write([]byte("foo\n"))
if err == syscall.EPIPE {
// never called => ko
fmt.Println("EPIPE error")
}
}
}
注意:作為一個簡單的Go練習,我嘗試實現一個幾乎與tee -a <a_file>
(將stdin打印到stdout和<a_file>
)類似的命令,其特定性如下: 非阻塞在命名管道和可選的reader上寫入 。
返回的錯誤不是普通的syscall.Error
,而是包裝在*os.PathError
如代碼的以下變體所示:
package main
import (
"fmt"
"os"
"syscall"
)
func main() {
// open previously created named pipe (`mkfifo /tmp/test`)
pipe, _ := os.OpenFile("/tmp/test", os.O_WRONLY, 0)
for {
n, err := pipe.Write([]byte("foo\n"))
fmt.Printf("write: n=%v, err=(%T) %[2]v\n", n, err)
if err == syscall.EPIPE {
fmt.Println("EPIPE error")
} else if perr, ok := err.(*os.PathError); ok {
fmt.Printf("op: %q; path=%q; err=(%T) %[3]q\n",
perr.Op, perr.Path, perr.Err)
if perr.Err == syscall.EPIPE {
fmt.Println("os.PathError.Err is EPIPE")
}
}
}
}
在執行mkfifo /tmp/test; head /tmp/test
之后運行此程序mkfifo /tmp/test; head /tmp/test
mkfifo /tmp/test; head /tmp/test
在其他地方給我:
write: n=4, err=(<nil>) <nil>
[… repeated nine more times, as the head command reads ten lines …]
write: n=0, err=(*os.PathError) write /tmp/test: broken pipe
op: "write"; path="/tmp/test"; err=(syscall.Errno) "broken pipe"
os.PathError.Err is EPIPE
[… above three lines repeated nine more times …]
signal: broken pipe
Exit 1
在單個文件上返回十個管道錯誤后,Go runtine停止捕獲/阻止SIGPIPE,並將其傳遞到程序中將其殺死。 我不相信Go運行時會在內部使用SIGPIPE來捕獲或忽略它。
有兩件事:一,要查找syscall.EPIPE
您需要檢查*os.PathError
,如圖所示;二,當您實際未處理錯誤時,當err != nil
時不要繼續操作。
我不知道為什么Go用這種方式處理SIGPIPE的細節。 也許搜索Go的bug跟蹤器和/或go-nuts列表可能有助於回答這一問題。 在Go 1.5的os/signal
包中添加了signal.Reset(syscall.SIGPIPE)
(在任何signal.Notify
調用之前)會更改此行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.