From 066247a08fb383aa3651a5e0ea15354c2d3685ee Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 31 May 2023 18:07:06 -0400 Subject: [PATCH] Add daemon utilities --- daemon/daemon.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 daemon/daemon.go diff --git a/daemon/daemon.go b/daemon/daemon.go new file mode 100644 index 0000000..f47af2e --- /dev/null +++ b/daemon/daemon.go @@ -0,0 +1,50 @@ +// Package daemon provides utilities for daemons. +package daemon + +import "io" +import "os" +import "syscall" +import "strconv" +import "os/signal" + +// PidFile is a string that contains a path to a pidfile. +type PidFile string + +// Start writes to the pidfile. +func (pidfile PidFile) Start () error { + return os.WriteFile(string(pidfile), []byte(strconv.Itoa(os.Getpid())), 0644) +} + +// Close deletes the pidfile. +func (pidfile PidFile) Close () error { + return os.Remove(string(pidfile)) +} + +// Empty returns true if the object is zero value (an empty string). +func (pidfile PidFile) Empty () bool { + return pidfile == "" +} + +// OnSigint calls the specified function once sigint is recieved. This function +// does not block, and spawns a goroutine that waits. For this reason, the +// callback must be safe to call concurrently. +func OnSigint (callback func ()) { + go func () { + sigintNotify := make(chan os.Signal, 1) + signal.Notify(sigintNotify, os.Interrupt, syscall.SIGTERM) + + <-sigintNotify + callback() + } () +} + +// CloseOnSigint is like OnSigint, but takes an io.Closer. +func CloseOnSigint (closer io.Closer) { + OnSigint(func () { closer.Close() }) +} + +// ShutdownOnSigint is like OnSigint, but takes an object with a Shutdown() +// method. +func ShutdownOnSigint (shutdowner interface { Shutdown() error }) { + OnSigint(func () { shutdowner.Shutdown() }) +}