Bläddra i källkod

Initial commit

Oliver Soell 9 år sedan
förälder
incheckning
d482c90573
1 ändrade filer med 82 tillägg och 0 borttagningar
  1. 82 0
      pidfile.go

+ 82 - 0
pidfile.go

@@ -0,0 +1,82 @@
+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
+}