12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- package pidfile
- import (
- "errors"
- "fmt"
- "io/ioutil"
- "os"
- "strconv"
- "strings"
- "syscall"
- )
- var (
- ErrProcessRunning = errors.New("process is running")
- ErrFileStale = errors.New("pidfile exists but process is not running")
- ErrFileInvalid = errors.New("pidfile has invalid contents")
- )
- // Remove a pidfile
- func Remove(filename string) error {
- return os.RemoveAll(filename)
- }
- // Write writes a pidfile, returning an error
- // if the process is already running or pidfile is orphaned
- func Write(filename string) error {
- return WriteControl(filename, os.Getpid(), false)
- }
- func WriteControl(filename string, pid int, overwrite bool) error {
- // Check for existing pid
- oldpid, err := pidfileContents(filename)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- // We have a pid
- if err == nil {
- if pidIsRunning(oldpid) {
- return ErrProcessRunning
- }
- if !overwrite {
- return ErrFileStale
- }
- }
- // We're clear to (over)write the file
- return ioutil.WriteFile(filename, []byte(fmt.Sprintf("%d\n", pid)), 0644)
- }
- func pidfileContents(filename string) (int, error) {
- contents, err := ioutil.ReadFile(filename)
- if err != nil {
- return 0, err
- }
- pid, err := strconv.Atoi(strings.TrimSpace(string(contents)))
- if err != nil {
- return 0, ErrFileInvalid
- }
- return pid, nil
- }
- func pidIsRunning(pid int) bool {
- process, err := os.FindProcess(pid)
- if err != nil {
- return false
- }
- err = process.Signal(syscall.Signal(0))
- if err != nil && err.Error() == "no such process" {
- return false
- }
- if err != nil && err.Error() == "os: process already finished" {
- return false
- }
- return true
- }
|