I have an http server (launched using http.Handle
) and I would like to do some operations.
How can I do that (on linux) ? Is it possible to do those operations in case of a ctrl-C ?
I'm not familiar with unix signals so the answer may be trivial.
I have an http server (launched using http.Handle
) and I would like to do some operations.
How can I do that (on linux) ? Is it possible to do those operations in case of a ctrl-C ?
I'm not familiar with unix signals so the answer may be trivial.
You can subscribe to the TERM and INT signals using the signal package. But note that these signals are only sent when the process is killed explicitly; normal exit (initiated by the process itself) does not involve any sort of signals. I think for normal exit just do something in the main routine (which supposedly should spawn worker goroutines and then wait on them).
Read man 7 signal
for more general info on POSIX signals.
Using kostix answer, I built this code (now adapted to Go1) to catch the interrupt signal and do some operations before exiting :
go func() {
sigchan := make(chan os.Signal, 10)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
log.Println("Program killed !")
// do last actions and wait for all write operations to end
os.Exit(0)
}()
// start main program tasks
I suppose author is interested not only in Ctrl+C and offer more broad solution for Linux (for Windows signals see x/sys/windows):
package main
import (
"os"
"os/signal"
"syscall"
"fmt"
)
func getFireSignalsChannel() chan os.Signal {
c := make(chan os.Signal, 1)
signal.Notify(c,
// https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
syscall.SIGINT, // Ctrl+C
syscall.SIGQUIT, // Ctrl-\
syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
syscall.SIGHUP, // "terminal is disconnected"
)
return c
}
func exit() {
syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
}
func main() {
exitChan := getFireSignalsChannel()
input, err := os.Open("input.txt")
if err != nil {
panic(err)
}
defer input.Close()
<-exitChan
fmt.Println("Exiting!")
return
// All main deferreds executed here even in case of panic.
// Non-main deferreds are not executed here.
}
P.S. None of signals handles os.Exit
.
With this configuration on Ctrl+C or on receiving other signal program will push os.Signal
into channel exitChan
which will unblock <-exitChan
operation and the main
function will continue execution on the final lines, then return, then execute deferred functions.
For non-main deferred you may: