Setup daemon pidfile/cleanup in Server.Daemon() instead of main()

This commit is contained in:
Solomon Hykes 2013-10-25 00:30:34 -06:00
Родитель c542b2f873
Коммит c1ae1a0e1c
3 изменённых файлов: 67 добавлений и 57 удалений

Просмотреть файл

@ -7,13 +7,9 @@ import (
"github.com/dotcloud/docker/sysinit"
"github.com/dotcloud/docker/utils"
"github.com/dotcloud/docker/engine"
"io/ioutil"
"log"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
)
var (
@ -89,7 +85,7 @@ func main() {
job.SetenvList("ProtoAddresses", flHosts)
job.Setenv("DefaultIp", *flDefaultIp)
job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
if err := daemon(job, *pidfile); err != nil {
if err := job.Run(); err != nil {
log.Fatal(err)
}
} else {
@ -109,50 +105,3 @@ func main() {
func showVersion() {
fmt.Printf("Docker version %s, build %s\n", VERSION, GITCOMMIT)
}
func createPidFile(pidfile string) error {
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
pid, err := strconv.Atoi(string(pidString))
if err == nil {
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
}
}
}
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 err := os.Remove(pidfile); err != nil {
log.Printf("Error removing %s: %s", pidfile, err)
}
}
// daemon runs `job` as a daemon.
// A pidfile is created for the duration of the job,
// and all signals are intercepted.
func daemon(job *engine.Job, pidfile string) error {
if err := createPidFile(pidfile); err != nil {
log.Fatal(err)
}
defer removePidFile(pidfile)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
go func() {
sig := <-c
log.Printf("Received signal '%v', exiting\n", sig)
removePidFile(pidfile)
os.Exit(0)
}()
return job.Run()
}

Просмотреть файл

@ -24,6 +24,7 @@ import (
"sync"
"time"
"syscall"
"os/signal"
)
func (srv *Server) Close() error {
@ -40,8 +41,31 @@ func JobServeApi(job *engine.Job) string {
return err.Error()
}
defer srv.Close()
// Parse addresses to serve on
protoAddrs := job.Args
if err := srv.Daemon(); err != nil {
return err.Error()
}
return "0"
}
// Daemon runs the remote api server `srv` as a daemon,
// Only one api server can run at the same time - this is enforced by a pidfile.
// The signals SIGINT, SIGKILL and SIGTERM are intercepted for cleanup.
func (srv *Server) Daemon() error {
if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
log.Fatal(err)
}
defer utils.RemovePidFile(srv.runtime.config.Pidfile)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
go func() {
sig := <-c
log.Printf("Received signal '%v', exiting\n", sig)
utils.RemovePidFile(srv.runtime.config.Pidfile)
os.Exit(0)
}()
protoAddrs := srv.runtime.config.ProtoAddresses
chErrors := make(chan error, len(protoAddrs))
for _, protoAddr := range protoAddrs {
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
@ -52,7 +76,7 @@ func JobServeApi(job *engine.Job) string {
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
}
} else {
return "Invalid protocol format."
return fmt.Errorf("Invalid protocol format.")
}
go func() {
chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, true)
@ -61,12 +85,13 @@ func JobServeApi(job *engine.Job) string {
for i := 0; i < len(protoAddrs); i += 1 {
err := <-chErrors
if err != nil {
return err.Error()
return err
}
}
return "0"
return nil
}
func (srv *Server) DockerVersion() APIVersion {
return APIVersion{
Version: VERSION,

36
utils/daemon.go Normal file
Просмотреть файл

@ -0,0 +1,36 @@
package utils
import (
"os"
"fmt"
"io/ioutil"
"log"
"strconv"
)
func CreatePidFile(pidfile string) error {
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
pid, err := strconv.Atoi(string(pidString))
if err == nil {
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
}
}
}
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 err := os.Remove(pidfile); err != nil {
log.Printf("Error removing %s: %s", pidfile, err)
}
}