From 4b5b1a2409784590456f14d501b484000a6f9a52 Mon Sep 17 00:00:00 2001
From: Valentin Rothberg <rothberg@redhat.com>
Date: Fri, 20 Sep 2019 09:30:49 +0200
Subject: [PATCH] get dnsmasq process: lookup in proc FS

Golang`s `os.FindProcess()` always returns success on UNIX machines -
even when the PID doesn't exist.  Hence, add a lookup in the proc FS
to check if the given exists or not.  That's okay since dnsmane is
targetting Linux only.

Also rename the method to `getProcess()` and add some comments.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
---
 plugins/meta/dnsname/dnsname_test.go |  4 ++--
 plugins/meta/dnsname/main.go         |  2 +-
 plugins/meta/dnsname/service.go      | 16 +++++++++++-----
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/plugins/meta/dnsname/dnsname_test.go b/plugins/meta/dnsname/dnsname_test.go
index 9646d8b..5bc4032 100644
--- a/plugins/meta/dnsname/dnsname_test.go
+++ b/plugins/meta/dnsname/dnsname_test.go
@@ -127,7 +127,7 @@ var _ = Describe("dnsname tests", func() {
 			Expect(err).To(BeNil())
 
 			// Check that the dns masq instance is running
-			pid, err := d.getPidProcess()
+			pid, err := d.getProcess()
 			Expect(err).To(BeNil())
 			// Send it a signal 0; if alive, error will be nil
 			err = pid.Signal(syscall.Signal(0))
@@ -166,7 +166,7 @@ var _ = Describe("dnsname tests", func() {
 			d, err := newDNSMasqFile("foobar.io", "dummy0", "test")
 			Expect(err).To(BeNil())
 
-			pid, err := d.getPidProcess()
+			pid, err := d.getProcess()
 			Expect(err).To(BeNil())
 			err = pid.Signal(syscall.Signal(0))
 			Expect(err).To(BeNil())
diff --git a/plugins/meta/dnsname/main.go b/plugins/meta/dnsname/main.go
index 8630480..4b49f13 100644
--- a/plugins/meta/dnsname/main.go
+++ b/plugins/meta/dnsname/main.go
@@ -186,7 +186,7 @@ func cmdCheck(args *skel.CmdArgs) error {
 		}
 	}()
 
-	pid, err := dnsNameConf.getPidProcess()
+	pid, err := dnsNameConf.getProcess()
 	if err != nil {
 		return err
 	}
diff --git a/plugins/meta/dnsname/service.go b/plugins/meta/dnsname/service.go
index 93c4ee3..6922ad4 100644
--- a/plugins/meta/dnsname/service.go
+++ b/plugins/meta/dnsname/service.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 	"syscall"
 
+	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 )
 
@@ -38,7 +39,7 @@ func (d dnsNameFile) hup() error {
 	if _, err := os.Stat(d.PidFile); os.IsNotExist(err) {
 		return d.start()
 	}
-	pid, err := d.getPidProcess()
+	pid, err := d.getProcess()
 	if err != nil {
 		return err
 	}
@@ -57,6 +58,7 @@ func isRunning(pid *os.Process) bool {
 	return true
 }
 
+// start starts the dnsmasq instance.
 func (d dnsNameFile) start() error {
 	args := []string{
 		"-u",
@@ -67,17 +69,18 @@ func (d dnsNameFile) start() error {
 	return cmd.Run()
 }
 
+// stop stops the dnsmasq instance.
 func (d dnsNameFile) stop() error {
-	pid, err := d.getPidProcess()
+	pid, err := d.getProcess()
 	if err != nil {
 		return err
 	}
 	return pid.Kill()
 }
 
-// getPidProcess reads the PID for the dnsmasq instance and returns it in the
-// form of an int
-func (d dnsNameFile) getPidProcess() (*os.Process, error) {
+// getProcess reads the PID for the dnsmasq instance and returns an
+// *os.Process. Returns an error if the PID does not exist.
+func (d dnsNameFile) getProcess() (*os.Process, error) {
 	pidFileContents, err := ioutil.ReadFile(d.PidFile)
 	if err != nil {
 		return nil, err
@@ -86,6 +89,9 @@ func (d dnsNameFile) getPidProcess() (*os.Process, error) {
 	if err != nil {
 		return nil, err
 	}
+	if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); os.IsNotExist(err) {
+		return nil, errors.Wrapf(err, "dnsmasq process with PID %d does not exist", pid)
+	}
 	return os.FindProcess(pid)
 }
 
-- 
GitLab