-
Notifications
You must be signed in to change notification settings - Fork 165
/
Copy pathpidfile.go
106 lines (93 loc) · 2.67 KB
/
pidfile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (c) 2018 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0
// Manage pidfile in /run/
package pidfile
import (
"fmt"
"os"
"path"
"strconv"
"syscall"
"github.com/lf-edge/eve/pkg/pillar/base"
)
const (
defaultRundir = "/run"
)
func writeMyPid(filename string) error {
pid := os.Getpid()
pidStr := fmt.Sprintf("%d", pid)
b := []byte(pidStr)
// if the directory does not exist, try to create it
if err := os.MkdirAll(path.Dir(filename), 0755); err != nil {
return err
}
return os.WriteFile(filename, b, 0644)
}
// CheckProcessExists returns true if agent process is running
// returns string with description of check result
func CheckProcessExists(log *base.LogObject, agentName string, options ...Option) (bool, string) {
opt := processOpts(options)
return checkProcessExists(log, agentName, opt)
}
func checkProcessExists(log *base.LogObject, agentName string, opt opt) (bool, string) {
filename := path.Join(opt.baseDir, agentName+".pid")
if _, err := os.Stat(filename); err != nil && os.IsNotExist(err) {
return false, err.Error()
}
log.Functionf("CheckProcessExists: found %s\n", filename)
// Check if process still exists
b, err := os.ReadFile(filename)
if err != nil {
log.Fatalf("CheckProcessExists: %s", err)
}
oldPid, err := strconv.Atoi(string(b))
if err != nil {
return false, fmt.Sprintf("atoi of %s failed %s", filename, err)
}
// Does the old pid exist?
p, err := os.FindProcess(oldPid)
if err == nil {
err = p.Signal(syscall.Signal(0))
if err == nil {
return true, fmt.Sprintf("old pid %d exists for agent %s", oldPid, agentName)
}
}
return false, fmt.Sprintf("no running process found for agent %s", agentName)
}
// CheckAndCreatePidfile check if old process is not running and create new pid file
func CheckAndCreatePidfile(log *base.LogObject, agentName string, options ...Option) error {
opt := processOpts(options)
if exists, description := checkProcessExists(log, agentName, opt); exists {
return fmt.Errorf("checkAndCreatePidfile: %s", description)
}
rundir := defaultRundir
if opt.baseDir != "" {
rundir = opt.baseDir
}
filename := path.Join(rundir, agentName+".pid")
if err := writeMyPid(filename); err != nil {
log.Fatalf("checkAndCreatePidfile: %s", err)
}
return nil
}
func processOpts(options []Option) opt {
opt := opt{}
for _, o := range options {
o(&opt)
}
if opt.baseDir == "" {
opt.baseDir = defaultRundir
}
return opt
}
type opt struct {
baseDir string
}
// Option option function to pass to pidfile functions
type Option func(o *opt)
// WithBaseDir set the base directory for pidfiles. Default is /run.
func WithBaseDir(baseDir string) Option {
return func(o *opt) {
o.baseDir = baseDir
}
}