Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions utils/daemonize.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
"syscall"

"github.com/VividCortex/godaemon"
"github.com/leonsodhi/lockfile"
Expand All @@ -24,25 +25,24 @@ func ResolvePath(path string) string {
}

func Daemonize(logFilePath, pidFilePath string) {

if os.Getenv("__DAEMON_CWD") == "" {
cwd, err := os.Getwd()
if err != nil {
fmt.Fprintln(os.Stderr, "Cannot determine working directory: %v", err)
fmt.Fprintf(os.Stderr, "Cannot determine working directory: %v\n", err)
os.Exit(1)
}
os.Setenv("__DAEMON_CWD", cwd)
}

logFile, err := os.OpenFile(logFilePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
fmt.Fprintln(os.Stderr, "Could not open local log file: %v", err)
fmt.Fprintf(os.Stderr, "Could not open local log file: %v\n", err)
os.Exit(1)
}

stdout, stderr, err := godaemon.MakeDaemon(&godaemon.DaemonAttr{CaptureOutput: true})
if err != nil {
fmt.Fprintln(os.Stderr, "Could not Daemonize: %v", err)
fmt.Fprintf(os.Stderr, "Could not Daemonize: %v\n", err)
os.Exit(1)
}

Expand All @@ -54,10 +54,25 @@ func Daemonize(logFilePath, pidFilePath string) {
}()

lock, err := lockfile.New(pidFilePath)

removePidFile := func() {
fmt.Fprintf(os.Stderr, "Removing %s\n", pidFilePath)
lock.Unlock()
}

err = lock.TryLock()
if err != nil {
fmt.Println("Cannot lock \"%v\": %v", lock, err)
fmt.Fprintf(os.Stderr, "Cannot lock \"%v\", error was %v\n", lock, err)

// Temporary workaround to transition from existing daemon
if err.Error() == "os: process already finished" {
removePidFile()
}

os.Exit(1)
}

SignalHandlers[syscall.SIGINT] = removePidFile // Terminate
SignalHandlers[syscall.SIGTERM] = removePidFile // Terminate
SignalHandlers[syscall.SIGQUIT] = removePidFile // Stop gracefully
}
56 changes: 35 additions & 21 deletions utils/signals.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,46 @@
package utils

import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"runtime"
"syscall"
"os/signal"
"io/ioutil"
)

var SignalHandlers = map[os.Signal]func(){
syscall.SIGUSR1: dumpStacks, // Dump goroutines stacks
}

func AddSignalHandlers() {
var trapped []os.Signal
for k := range SignalHandlers {
trapped = append(trapped, k)
}

signals := make(chan os.Signal, 1)
signal.Notify(signals, trapped...)

go func() {
for sig := range signals {
if f, found := SignalHandlers[sig]; found {
fmt.Fprintf(os.Stderr, "Handling signal: %v\n", sig)
f()
}

switch sig {
case syscall.SIGINT, syscall.SIGTERM:
os.Exit(128 + int(sig.(syscall.Signal)))
case syscall.SIGQUIT:
os.Exit(0)
}
}
}()
}

// Mostly copied from Docker
func dumpStacks() {
func dumpStacks() {
var (
buf []byte
stackSize int
Expand All @@ -28,25 +59,8 @@ func dumpStacks() {

f, err := ioutil.TempFile("", "r_s_stacktrace")
defer f.Close()
if (err == nil) {
if err == nil {
f.WriteString(string(buf))
}


}

func AddSignalHandlers() {
sigChan := make(chan os.Signal, 1)
go func() {
for sig := range sigChan {
go func(sig os.Signal) {
switch sig {
case syscall.SIGUSR1:
dumpStacks()
}
}(sig)

}
}()
signal.Notify(sigChan, syscall.SIGUSR1)
}