Skip to content

Commit 7147878

Browse files
authored
Merge pull request #815 from devlights/add-mkfifo-read-example
2 parents 8386bbe + 5ccaf43 commit 7147878

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tmp-fifo
2+
app
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
vars:
6+
FIFO_FILE: ./tmp-fifo
7+
8+
tasks:
9+
default:
10+
cmds:
11+
- task: build
12+
- task: create-fifo
13+
- task: run
14+
build:
15+
cmds:
16+
- go build -o app .
17+
create-fifo:
18+
cmds:
19+
- rm -f {{.FIFO_FILE}}
20+
- mkfifo {{.FIFO_FILE}} -m0666
21+
run:
22+
cmds:
23+
# ワザと書込みを遅延させて実行
24+
- (sleep 3; echo "helloworld" > {{.FIFO_FILE}}) &
25+
- ./app -fname {{.FIFO_FILE}}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//go:build linux
2+
3+
package main
4+
5+
import (
6+
"bufio"
7+
"flag"
8+
"log"
9+
"os"
10+
"time"
11+
)
12+
13+
var (
14+
fname string
15+
)
16+
17+
func init() {
18+
log.SetFlags(log.Lmicroseconds)
19+
20+
flag.StringVar(&fname, "fname", "", "FIFO file name")
21+
flag.Parse()
22+
}
23+
24+
func main() {
25+
if err := run(); err != nil {
26+
log.Fatal(err)
27+
}
28+
}
29+
30+
func run() error {
31+
//
32+
// 名前付きパイプを開く
33+
// os.OpenFile() にて、モード指定で os.ModeNamedPipe を指定する
34+
// os.O_RDOONLYで開くと読み取り専用となるが、この場合書込みが発生するまで
35+
// ブロックされる。これはUNIXの名前付きパイプの挙動に従った動作である。
36+
//
37+
var (
38+
f *os.File
39+
err error
40+
)
41+
42+
log.Println("[Before] os.OpenFile(os.O_RDOONLY)")
43+
44+
// 対象となる名前付きパイプに書込みが発生していない場合、ここでブロックされる。
45+
f, err = os.OpenFile(fname, os.O_RDONLY, os.ModeNamedPipe)
46+
if err != nil {
47+
return err
48+
}
49+
defer f.Close()
50+
51+
log.Println("[After ] os.OpenFile(os.O_RDOONLY)")
52+
53+
//
54+
// データを読み取り
55+
//
56+
type (
57+
data struct {
58+
value string
59+
err error
60+
}
61+
)
62+
var (
63+
reader = bufio.NewReader(f)
64+
lines = make(chan data)
65+
timeout = time.Second
66+
)
67+
68+
go func() {
69+
line, err := reader.ReadString('\n')
70+
lines <- data{line, err}
71+
}()
72+
73+
select {
74+
case line := <-lines:
75+
if line.err != nil {
76+
return line.err
77+
}
78+
79+
log.Println(line.value)
80+
case <-time.After(timeout):
81+
// 上記で記載した通り、os.O_RDOONLYのみで開いている場合
82+
// ブロッキングモードとなっているため、os.OpenFile()の呼び出しの
83+
// 時点でブロックされることとなる。つまり、実際にデータを読み出す
84+
// タイミングでは待たされることが無いため、このタイムアウトは通らない。
85+
log.Println("timeout")
86+
}
87+
88+
return nil
89+
}

0 commit comments

Comments
 (0)