Skip to content

Commit 0f3e6bc

Browse files
authored
Merge pull request #578 from devlights/add-send-signal-example
2 parents 307ea43 + 5d1d80b commit 0f3e6bc

File tree

7 files changed

+159
-0
lines changed

7 files changed

+159
-0
lines changed

examples/signal/send/Taskfile.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
version: "3"
2+
3+
tasks:
4+
default:
5+
cmds:
6+
- task: run-receiver
7+
- ps
8+
- task: run-sender
9+
- ps
10+
run-receiver:
11+
dir: receiver
12+
cmds:
13+
- go clean
14+
- go build -o receiver main.go
15+
- ./receiver &
16+
run-sender:
17+
dir: sender
18+
cmds:
19+
- go clean
20+
- go build -o sender main.go
21+
- ./sender
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
receiver
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//go:build !windows
2+
3+
// シグナルを受信する側です
4+
//
5+
// # 処理手順
6+
//
7+
// - signal.NotifyContext を利用して SIGTERM をフック
8+
// - シグナルが送信されるのを待機
9+
//
10+
// REFERENCES:
11+
// - https://stackoverflow.com/questions/9030680/list-of-currently-running-process-in-go
12+
package main
13+
14+
import (
15+
"context"
16+
"log"
17+
"os"
18+
"os/signal"
19+
"syscall"
20+
"time"
21+
)
22+
23+
var (
24+
appLog = log.New(os.Stderr, "[receiver] >>> ", 0)
25+
)
26+
27+
func main() {
28+
var (
29+
mainCtx = context.Background()
30+
procCtx, procCxl = context.WithTimeout(mainCtx, 10*time.Second)
31+
)
32+
defer procCxl()
33+
34+
signalCtx, signalCxl := signal.NotifyContext(procCtx, syscall.SIGTERM)
35+
defer signalCxl()
36+
37+
appLog.Println("wait for SIGTERM")
38+
select {
39+
case <-procCtx.Done():
40+
appLog.Println("timeout")
41+
case <-signalCtx.Done():
42+
appLog.Println("receive SIGTERM from sender")
43+
}
44+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sender
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//go:build !windows
2+
3+
// シグナルを送信する側です
4+
//
5+
// # 処理手順
6+
//
7+
// - receiver プロセスを探して pid を取得
8+
// - 対象 pid に対して SIGTERM を送る
9+
//
10+
// REFERENCES:
11+
// - https://stackoverflow.com/questions/9030680/list-of-currently-running-process-in-go
12+
package main
13+
14+
import (
15+
"errors"
16+
"log"
17+
"os"
18+
"path/filepath"
19+
"strconv"
20+
"strings"
21+
"syscall"
22+
)
23+
24+
const (
25+
procName = "receiver"
26+
)
27+
28+
var (
29+
appLog = log.New(os.Stderr, "[sender ] >>> ", 0)
30+
)
31+
32+
func main() {
33+
pid, err := find(procName)
34+
if err != nil {
35+
panic(err)
36+
}
37+
38+
if pid == -1 {
39+
panic("receiver pid not found")
40+
}
41+
42+
proc, err := os.FindProcess(pid)
43+
if err != nil {
44+
panic(err)
45+
}
46+
47+
appLog.Printf("send SIGTERM to receiver(%d)", pid)
48+
err = proc.Signal(syscall.SIGTERM)
49+
if err != nil {
50+
panic(err)
51+
}
52+
}
53+
54+
func find(name string) (int, error) {
55+
var (
56+
matches []string
57+
err error
58+
pid = -1
59+
)
60+
61+
matches, err = filepath.Glob("/proc/*/exe")
62+
if err != nil {
63+
return pid, err
64+
}
65+
66+
for _, f := range matches {
67+
real, err := os.Readlink(f)
68+
if err != nil && !errors.Is(err, os.ErrPermission) {
69+
return pid, err
70+
}
71+
72+
if len(real) > 0 && strings.Contains(real, "receiver") {
73+
dir := filepath.Base(filepath.Dir(f))
74+
75+
pid, err = strconv.Atoi(dir)
76+
if err != nil {
77+
return pid, err
78+
}
79+
80+
appLog.Printf("receiver pid is %v\n", pid)
81+
break
82+
}
83+
}
84+
85+
return pid, nil
86+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: "3"
2+
3+
tasks:
4+
default:
5+
cmds:
6+
- go run main.go
File renamed without changes.

0 commit comments

Comments
 (0)