Skip to content

Commit

Permalink
separate pidfile package from main
Browse files Browse the repository at this point in the history
  • Loading branch information
Songmu committed Feb 21, 2017
1 parent e13d0fd commit bc8bba7
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 73 deletions.
5 changes: 3 additions & 2 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/mackerelio/mackerel-agent/command"
"github.com/mackerelio/mackerel-agent/config"
"github.com/mackerelio/mackerel-agent/mackerel"
"github.com/mackerelio/mackerel-agent/pidfile"
"github.com/mackerelio/mackerel-agent/supervisor"
"github.com/mackerelio/mackerel-agent/version"
)
Expand Down Expand Up @@ -73,11 +74,11 @@ func doSupervise(fs *flag.FlagSet, argv []string) error {
return err
}
setLogLevel(conf.Silent, conf.Verbose)
err = createPidFile(conf.Pidfile)
err = pidfile.Create(conf.Pidfile)
if err != nil {
return err
}
defer removePidFile(conf.Pidfile)
defer pidfile.Remove(conf.Pidfile)

return supervisor.Supervise(os.Args[0], copiedArgv, nil)
}
Expand Down
50 changes: 4 additions & 46 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"os/signal"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"syscall"
"time"

"github.com/mackerelio/mackerel-agent/command"
"github.com/mackerelio/mackerel-agent/config"
"github.com/mackerelio/mackerel-agent/logging"
"github.com/mackerelio/mackerel-agent/util"
"github.com/mackerelio/mackerel-agent/pidfile"
"github.com/mackerelio/mackerel-agent/version"
"github.com/motemen/go-cli"
)
Expand Down Expand Up @@ -160,45 +157,6 @@ func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) {
return conf, nil
}

func createPidFile(pidfile string) error {
if pidfile == "" {
return nil
}
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
if pid, err := strconv.Atoi(string(pidString)); err == nil {
if util.ExistsPid(pid) {
return fmt.Errorf("pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
}
// Note mackerel-agent in windows can't remove pidfile during stoping the service
logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
} else {
logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
}
}

err := os.MkdirAll(filepath.Dir(pidfile), 0755)
if err != nil {
return err
}
file, err := os.Create(pidfile)
if err != nil {
return err
}
defer file.Close()

_, err = fmt.Fprintf(file, "%d", os.Getpid())
return err
}

func removePidFile(pidfile string) {
if pidfile == "" {
return
}
if err := os.Remove(pidfile); err != nil {
logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
}
}

func setLogLevel(silent, verbose bool) {
if silent {
logging.SetLogLevel(logging.ERROR)
Expand All @@ -212,10 +170,10 @@ func start(conf *config.Config, termCh chan struct{}) error {
setLogLevel(conf.Silent, conf.Verbose)
logger.Infof("Starting mackerel-agent version:%s, rev:%s, apibase:%s", version.VERSION, version.GITCOMMIT, conf.Apibase)

if err := createPidFile(conf.Pidfile); err != nil {
return fmt.Errorf("createPidFile(%q) failed: %s", conf.Pidfile, err)
if err := pidfile.Create(conf.Pidfile); err != nil {
return fmt.Errorf("pidfile.Create(%q) failed: %s", conf.Pidfile, err)
}
defer removePidFile(conf.Pidfile)
defer pidfile.Remove(conf.Pidfile)

ctx, err := command.Prepare(conf)
if err != nil {
Expand Down
13 changes: 7 additions & 6 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/mackerelio/mackerel-agent/command"
"github.com/mackerelio/mackerel-agent/pidfile"
)

func TestParseFlags(t *testing.T) {
Expand Down Expand Up @@ -130,25 +131,25 @@ func TestCreateAndRemovePidFile(t *testing.T) {
fpath := file.Name()
defer os.Remove(fpath)

err = createPidFile(fpath)
err = pidfile.Create(fpath)
if err != nil {
t.Errorf("pid file should be created but, %s", err)
}

if runtime.GOOS != "windows" {
if err := createPidFile(fpath); err == nil || !strings.HasPrefix(err.Error(), "pidfile found, try stopping another running mackerel-agent or delete") {
if err := pidfile.Create(fpath); err == nil || !strings.HasPrefix(err.Error(), "pidfile found, try stopping another running mackerel-agent or delete") {
t.Errorf("creating pid file should be failed when the running process exists, %s", err)
}
}

removePidFile(fpath)
if err := createPidFile(fpath); err != nil {
pidfile.Remove(fpath)
if err := pidfile.Create(fpath); err != nil {
t.Errorf("pid file should be created but, %s", err)
}

removePidFile(fpath)
pidfile.Remove(fpath)
ioutil.WriteFile(fpath, []byte(fmt.Sprint(math.MaxInt32)), 0644)
if err := createPidFile(fpath); err != nil {
if err := pidfile.Create(fpath); err != nil {
t.Errorf("old pid file should be ignored and new pid file should be created but, %s", err)
}
}
Expand Down
4 changes: 2 additions & 2 deletions util/pid.go → pidfile/pid.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package util
package pidfile

// ExistsPid check if pid exists
// ExistsPid checks if pid exists
func ExistsPid(pid int) bool {
return existsPid(pid)
}
2 changes: 1 addition & 1 deletion util/pid_darwin.go → pidfile/pid_darwin.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package util
package pidfile

import (
"fmt"
Expand Down
2 changes: 1 addition & 1 deletion util/pid_test.go → pidfile/pid_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build linux freebsd darwin netbsd

package util
package pidfile

import (
"math"
Expand Down
2 changes: 1 addition & 1 deletion util/pid_unix.go → pidfile/pid_unix.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build linux freebsd netbsd

package util
package pidfile

import (
"fmt"
Expand Down
2 changes: 1 addition & 1 deletion util/pid_windows.go → pidfile/pid_windows.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package util
package pidfile

func existsPid(_ int) bool {
// XXX not implemented. should use `tasklist` command or so
Expand Down
54 changes: 54 additions & 0 deletions pidfile/pidfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package pidfile

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"

"github.com/mackerelio/mackerel-agent/logging"
)

var logger = logging.GetLogger("pidfile")

// Create pidfile
func Create(pidfile string) error {
if pidfile == "" {
return nil
}
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
if pid, err := strconv.Atoi(string(pidString)); err == nil {
if ExistsPid(pid) {
return fmt.Errorf("pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
}
// Note mackerel-agent in windows can't remove pidfile during stoping the service
logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
} else {
logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
}
}

err := os.MkdirAll(filepath.Dir(pidfile), 0755)
if err != nil {
return err
}
file, err := os.Create(pidfile)
if err != nil {
return err
}
defer file.Close()

_, err = fmt.Fprintf(file, "%d", os.Getpid())
return err
}

// Remove pidfile
func Remove(pidfile string) {
if pidfile == "" {
return
}
if err := os.Remove(pidfile); err != nil {
logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
}
}
26 changes: 13 additions & 13 deletions supervisor/supervisor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"
"time"

"github.com/mackerelio/mackerel-agent/util"
"github.com/mackerelio/mackerel-agent/pidfile"
)

const stubAgent = "testdata/stub-agent"
Expand All @@ -33,7 +33,7 @@ func Testsupervisor(t *testing.T) {
}()
time.Sleep(50 * time.Millisecond)
pid := sv.getCmd().Process.Pid
if !util.ExistsPid(pid) {
if !pidfile.ExistsPid(pid) {
t.Errorf("process doesn't exist")
}
time.Sleep(50 * time.Millisecond)
Expand All @@ -43,7 +43,7 @@ func Testsupervisor(t *testing.T) {
if err != nil {
t.Errorf("error should be nil but: %v", err)
}
if util.ExistsPid(pid) {
if pidfile.ExistsPid(pid) {
t.Errorf("child process isn't terminated")
}
}
Expand All @@ -60,7 +60,7 @@ func Testsupervisor_reload(t *testing.T) {
}()
time.Sleep(50 * time.Millisecond)
oldPid := sv.getCmd().Process.Pid
if !util.ExistsPid(oldPid) {
if !pidfile.ExistsPid(oldPid) {
t.Errorf("process doesn't exist")
}
ch <- syscall.SIGHUP
Expand All @@ -69,10 +69,10 @@ func Testsupervisor_reload(t *testing.T) {
if oldPid == newPid {
t.Errorf("reload failed")
}
if util.ExistsPid(oldPid) {
if pidfile.ExistsPid(oldPid) {
t.Errorf("old process isn't terminated")
}
if !util.ExistsPid(newPid) {
if !pidfile.ExistsPid(newPid) {
t.Errorf("new process doesn't exist")
}
ch <- syscall.SIGTERM
Expand All @@ -83,7 +83,7 @@ func Testsupervisor_reload(t *testing.T) {
if newPid != sv.getCmd().Process.Pid {
t.Errorf("something went wrong")
}
if util.ExistsPid(newPid) {
if pidfile.ExistsPid(newPid) {
t.Errorf("child process isn't terminated")
}
}
Expand All @@ -100,7 +100,7 @@ func Testsupervisor_reloadFail(t *testing.T) {
}()
time.Sleep(50 * time.Millisecond)
oldPid := sv.getCmd().Process.Pid
if !util.ExistsPid(oldPid) {
if !pidfile.ExistsPid(oldPid) {
t.Errorf("process doesn't exist")
}
ch <- syscall.SIGHUP
Expand All @@ -126,14 +126,14 @@ func Testsupervisor_launchFailed(t *testing.T) {
}()
time.Sleep(50 * time.Millisecond)
pid := sv.getCmd().Process.Pid
if !util.ExistsPid(pid) {
if !pidfile.ExistsPid(pid) {
t.Errorf("process doesn't exist")
}
err := <-done
if err == nil {
t.Errorf("something went wrong")
}
if util.ExistsPid(sv.getCmd().Process.Pid) {
if pidfile.ExistsPid(sv.getCmd().Process.Pid) {
t.Errorf("child process isn't terminated")
}
}
Expand All @@ -154,7 +154,7 @@ func Testsupervisor_crashRecovery(t *testing.T) {
}()
time.Sleep(50 * time.Millisecond)
oldPid := sv.getCmd().Process.Pid
if !util.ExistsPid(oldPid) {
if !pidfile.ExistsPid(oldPid) {
t.Errorf("process doesn't exist")
}
time.Sleep(spawnInterval)
Expand All @@ -167,10 +167,10 @@ func Testsupervisor_crashRecovery(t *testing.T) {
if oldPid == newPid {
t.Errorf("crash recovery failed")
}
if util.ExistsPid(oldPid) {
if pidfile.ExistsPid(oldPid) {
t.Errorf("old process isn't terminated")
}
if !util.ExistsPid(newPid) {
if !pidfile.ExistsPid(newPid) {
t.Errorf("new process doesn't exist")
}
ch <- syscall.SIGTERM
Expand Down

0 comments on commit bc8bba7

Please sign in to comment.