Skip to content

Commit

Permalink
Add check for other instances
Browse files Browse the repository at this point in the history
  • Loading branch information
Miguel-Dorta committed Nov 25, 2019
1 parent d55f763 commit b4ee377
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 1 deletion.
11 changes: 10 additions & 1 deletion cmd/cameraSort/main.go → cmd/CNETCAM_sort/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,24 @@ func init() {
log = logolang.NewLogger()
log.Level = logolang.LevelError

var verbose, version bool
var (
pidFile string
verbose, version bool
)
flag.StringVar(&from, "from", "", "Path to read the files")
flag.StringVar(&to, "to", "", "Path to put the files")
flag.StringVar(&pidFile, "pid", "/run/CNETCAM_sort.pid", "Path to pid file")
flag.BoolVar(&verbose, "verbose", false, "Verbose output")
flag.BoolVar(&verbose, "v", false, "Verbose output")
flag.BoolVar(&version, "version", false, "Print version and exit")
flag.BoolVar(&version, "V", false, "Print version and exit")
flag.Parse()

if err := utils.PID(pidFile); err != nil {
log.Criticalf("error checking for other instances: %s", err)
os.Exit(1)
}

if version {
fmt.Println(internal.Version)
os.Exit(0)
Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions pkg/utils/cron.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package utils

import "time"

func ExecuteEvery(f func(), d time.Duration) {
wait := time.NewTicker(d).C
for range wait {
f()
}
}
File renamed without changes.
File renamed without changes.
97 changes: 97 additions & 0 deletions pkg/utils/process.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package utils

import (
"errors"
"fmt"
"golang.org/x/sys/unix"
"io/ioutil"
"os"
"strconv"
)

// errCleanPID is the error returned when the
var errEmpty = errors.New("empty file")

// PID checks if other instances of the program is running (using the path to the .pid file provided).
// If so, it will exit with error code 0
// If not, it will create/update the .pid file provided
func PID(path string) error {
// Read pid from path
pid, err := readPID(path)
if err != nil {
// Create/overwrite pid file if it doesn't exist or is empty.
if errors.Is(err, os.ErrNotExist) || errors.Is(err, errEmpty) {
return createPID(path)
}

// If other error, return
return err
}

// Check if process with the pid provided exists
exists, err := processExists(pid)
if err != nil {
return err
}

// Exit if exists, create pid file otherwise
if exists {
os.Exit(1)
}
return createPID(path)
}

// createPID creates/overwrites the path provided with a file that contains this program's PID
func createPID(path string) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create pid file: %w", err)
}
defer f.Close()

if _, err = f.WriteString(strconv.Itoa(os.Getpid()) + "\n"); err != nil {
return fmt.Errorf("cannot write pid file: %w", err)
}

if err = f.Close(); err != nil {
return fmt.Errorf("error closing pid file: %w", err)
}
return nil
}

// readPID reads the pid from the path provided
func readPID(path string) (int, error) {
// Read data from path
data, err := ioutil.ReadFile(path)
if err != nil {
return 0, fmt.Errorf("error reading pid file: %w", err)
}

// Check it's not empty
if len(data) == 0 {
return 0, errEmpty
}

// Remove last linebreak
if data[len(data)-1] == '\n' {
data = data[:len(data)-1]
}

// Get the pid
pid, err := strconv.Atoi(string(data))
if err != nil {
return 0, fmt.Errorf("error parsing PID: %w", err)
}
return pid, nil
}

// processExists checks if a process with the pid provided exists
func processExists(pid int) (bool, error) {
if err := unix.Kill(pid, unix.Signal(0)); err != nil {
if !errors.Is(err, unix.ESRCH) {
return false, fmt.Errorf("error checking existence of process with pid %d: %w", pid, err)
}
return false, nil
}
return true, nil
}

0 comments on commit b4ee377

Please sign in to comment.