do actions on end of execution
Asked Answered
C

3

12

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.

Crocein answered 6/12, 2011 at 17:8 Comment(2)
The code would be good as a separate answer. I understand it's fine to answer your own question (and even accept it!) Attribution to kostix for sending you in the right direction is good too.Durr
Ok, I'l make a separate answer (with clear attribution).Coinage
V
4

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.

Viradis answered 6/12, 2011 at 17:30 Comment(0)
C
25

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)
    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
Crocein answered 21/6, 2012 at 5:23 Comment(2)
Why the size of sigchan is 10. I think make(chan os.Signal, 1) i.e with size 1 will work as well. Please let me know if I am missing anything.Saccharate
@PrakashPandey The unbuffered make(chan os.Signal) would work well for this scenario.Thermistor
H
5

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.

Non-Main Deferreds

For non-main deferred you may:

  1. Use https://github.com/tebeka/atexit
  2. Move important resources into global array and release them in a main deferred. This solution is not perfect if you don't use transaction: 1) create resource, 2) add to array, -- which shouldn't be interrupted by exit. Also non-concurrent read-write access to a slice must be provided I guess.
Humphreys answered 25/12, 2017 at 11:58 Comment(1)
Your code also works well in Windows. However, I find no way to listen to panics and Go crashes, other than directly defer in the main function. I tested here <github.com/patarapolw/atexit>Disseminate
V
4

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.

Viradis answered 6/12, 2011 at 17:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.