From e7ab6ad504b0a7524766717c9b68c2ac332f07f1 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 19 Mar 2018 08:38:18 +0100 Subject: [feat] only one systray can be in execution Create a systray.pid file to check if another systray is in execution and only one systray is allowed to be running. - Resolves: #17 --- main.go | 21 ++++++++++++--- pid.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ systray.go | 3 +++ 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 pid.go diff --git a/main.go b/main.go index 95f8ff4..0e067ca 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,12 @@ const ( var printer *message.Printer func main() { + err := acquirePID() + if err != nil { + log.Fatal(err) + } + defer releasePID() + conf := parseConfig() initPrinter() @@ -37,22 +43,28 @@ func main() { b, err := bitmask.Init() if err != nil { - log.Fatal(err) + log.Print(err) + return } defer b.Close() - checkAndInstallHelpers(b, notify) + err = checkAndInstallHelpers(b, notify) + if err != nil { + log.Printf("Is bitmask running? %v", err) + return + } + run(b, conf) } -func checkAndInstallHelpers(b *bitmask.Bitmask, notify *notificator) { +func checkAndInstallHelpers(b *bitmask.Bitmask, notify *notificator) error { helpers, priviledge, err := b.VPNCheck() if (err != nil && err.Error() == "nopolkit") || (err == nil && !priviledge) { log.Printf("No polkit found") notify.authAgent() } else if err != nil { notify.bitmaskNotRunning() - log.Fatal("Is bitmask running? ", err) + return err } if !helpers { @@ -61,6 +73,7 @@ func checkAndInstallHelpers(b *bitmask.Bitmask, notify *notificator) { log.Println("Error installing helpers: ", err) } } + return nil } func initPrinter() { diff --git a/pid.go b/pid.go new file mode 100644 index 0000000..0636110 --- /dev/null +++ b/pid.go @@ -0,0 +1,87 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "syscall" + + "0xacab.org/leap/bitmask-systray/bitmask" +) + +var pidFile = filepath.Join(bitmask.ConfigPath, "systray.pid") + +func acquirePID() error { + pid := syscall.Getpid() + current, err := getPID() + if err != nil { + return err + } + + if current != 0 && current != pid { + proc, err := os.FindProcess(current) + if err != nil { + return err + } + err = proc.Signal(syscall.Signal(0)) + if err == nil { + return fmt.Errorf("Another systray is running with pid: %d", current) + } + } + + return setPID(pid) +} + +func releasePID() error { + pid := syscall.Getpid() + current, err := getPID() + if err != nil { + return err + } + if current != 0 && current != pid { + return fmt.Errorf("Can't release pid file, is not own by this process") + } + + if current == pid { + return os.Remove(pidFile) + } + return nil +} + +func getPID() (int, error) { + _, err := os.Stat(pidFile) + if os.IsNotExist(err) { + return 0, nil + } + if err != nil { + return 0, err + } + + file, err := os.Open(pidFile) + if err != nil { + return 0, err + } + defer file.Close() + + b, err := ioutil.ReadAll(file) + if err != nil { + return 0, err + } + if len(b) == 0 { + return 0, nil + } + return strconv.Atoi(string(b)) +} + +func setPID(pid int) error { + file, err := os.Create(pidFile) + if err != nil { + return err + } + defer file.Close() + + _, err = file.WriteString(fmt.Sprintf("%d", pid)) + return err +} diff --git a/systray.go b/systray.go index e76763a..d72562c 100644 --- a/systray.go +++ b/systray.go @@ -116,7 +116,10 @@ func (bt *bmTray) onReady() { case <-mQuit.ClickedCh: systray.Quit() + // XXX: this a hack as quit doesn't work + // this should be done by defer in the main function bt.bm.Close() + releasePID() log.Println("Quit now...") os.Exit(0) -- cgit v1.2.3