Skip to content

Commit

Permalink
centralize registration of exit handlers
Browse files Browse the repository at this point in the history
Signed-off-by: Luca Stocchi <lstocchi@redhat.com>
  • Loading branch information
lstocchi committed Nov 29, 2024
1 parent 856b372 commit e659185
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 14 deletions.
4 changes: 4 additions & 0 deletions cmd/vfkit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
restvf "github.com/crc-org/vfkit/pkg/rest/vf"
"github.com/crc-org/vfkit/pkg/vf"
log "github.com/sirupsen/logrus"

"github.com/crc-org/vfkit/pkg/util"
)

func newLegacyBootloader(opts *cmdline.Options) config.Bootloader {
Expand Down Expand Up @@ -121,6 +123,8 @@ func runVFKit(vmConfig *config.VirtualMachine, opts *cmdline.Options) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

util.SetupExitSignalHandling()

gpuDevs := vmConfig.VirtioGPUDevices()
if opts.UseGUI && len(gpuDevs) > 0 {
gpuDevs[0].UsesGUI = true
Expand Down
44 changes: 44 additions & 0 deletions pkg/util/exithandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package util

import (
"log"
"os"
"os/signal"
"syscall"
)

var exitHandlers []func()

// RegisterExitHandler appends a func Exit handler to the list of handlers.
// The handlers will be invoked when vfkit receives a termination or interruption signal
//
// This method is useful when a caller wishes to execute a func before a shutdown.
func RegisterExitHandler(handler func()) {
exitHandlers = append(exitHandlers, handler)
}

// SetupExitSignalHandling sets up a signal channel to listen for termination or interruption signals.
// When one of these signals is received, all the registered exit handlers will be invoked, just
// before terminating the program.
func SetupExitSignalHandling() {
setupExitSignalHandling(true)
}

// setupExitSignalHandling sets up a signal channel to listen for termination or interruption signals.
// When one of these signals is received, all the registered exit handlers will be invoked.
// It is possible to prevent the program from exiting by setting the doExit param to false (used for testing)
func setupExitSignalHandling(doExit bool) {
sigChan := make(chan os.Signal, 2)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
go func() {
for sig := range sigChan {
log.Printf("captured %v, calling exit handlers and exiting..", sig)
for _, handler := range exitHandlers {
handler()
}
if doExit {
os.Exit(1)
}
}
}()
}
25 changes: 25 additions & 0 deletions pkg/util/exithandler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package util

import (
"syscall"
"testing"
"time"
)

func TestExitHandlerCalled(t *testing.T) {
setupExitSignalHandling(false)

ch := make(chan struct{})
RegisterExitHandler(func() {
close(ch)
})

syscall.Kill(syscall.Getpid(), syscall.SIGINT)

select {
case <-ch:
// exit handler was called
case <-time.After(5 * time.Second):
t.Errorf("Exit handler not called - timed out")
}
}
16 changes: 2 additions & 14 deletions pkg/vf/virtionet.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"math/rand"
"net"
"os"
"os/signal"
"path/filepath"
"syscall"

"github.com/crc-org/vfkit/pkg/config"
"github.com/crc-org/vfkit/pkg/util"

"github.com/Code-Hex/vz/v3"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -102,7 +102,7 @@ func (dev *VirtioNet) connectUnixPath() error {
dev.Socket = fd
dev.localAddr = &localAddr
dev.UnixSocketPath = ""
registerExitHandler(func() { _ = dev.Shutdown() })
util.RegisterExitHandler(func() { _ = dev.Shutdown() })
return nil
}

Expand Down Expand Up @@ -173,15 +173,3 @@ func (dev *VirtioNet) Shutdown() error {

return nil
}

func registerExitHandler(handler func()) {
sigChan := make(chan os.Signal, 2)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
go func() {
for sig := range sigChan {
log.Printf("captured %v, calling exit handlers and exiting..", sig)
handler()
os.Exit(1)
}
}()
}

0 comments on commit e659185

Please sign in to comment.