From 4f597b2478261175f660cec8175193859b44a1da Mon Sep 17 00:00:00 2001 From: Vladimir Hodakov Date: Thu, 12 Feb 2026 03:18:33 +0300 Subject: [PATCH] Fixed Ctrl-C handling --- cmd/faketunes/faketunes.go | 31 +++++++++++++---------- internal/application/application.go | 9 +++++++ internal/domains/filesystem/errors.go | 1 + internal/domains/filesystem/filesystem.go | 9 +++++-- internal/domains/filesystem/mount.go | 8 ++---- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/cmd/faketunes/faketunes.go b/cmd/faketunes/faketunes.go index e9f6de6..5e1db0f 100644 --- a/cmd/faketunes/faketunes.go +++ b/cmd/faketunes/faketunes.go @@ -4,6 +4,7 @@ import ( "context" "os" "os/signal" + "sync" "syscall" "source.hodakov.me/hdkv/faketunes/internal/application" @@ -36,6 +37,15 @@ func main() { app.Logger().Fatal(err) } + // CTRL+C handler. + interrupt := make(chan os.Signal, 1) + signal.Notify( + interrupt, syscall.SIGINT, syscall.SIGTERM, + ) + + var wg sync.WaitGroup + app.RegisterGlobalWaitGroup(&wg) + err = app.StartDomains() if err != nil { app.Logger().Fatal(err) @@ -43,24 +53,17 @@ func main() { app.Logger().Info("Started faketunes") - // CTRL+C handler. - interrupt := make(chan os.Signal, 1) - signal.Notify(interrupt) - - shutdownDone := make(chan bool, 1) - go func() { signalThing := <-interrupt - if signalThing == syscall.SIGTERM || signalThing == syscall.SIGINT { - app.Logger().WithField("signal", signalThing.String()). - Info("Got terminating signal, shutting down...") + app.Logger().WithField("signal", signalThing.String()). + Info("Got terminating signal, shutting down...") - cancel() - - shutdownDone <- true - } + cancel() }() - <-shutdownDone + // Wait for all domains to finish their cleanup + wg.Wait() + + app.Logger().Info("Faketunes shutdown complete") os.Exit(0) } diff --git a/internal/application/application.go b/internal/application/application.go index 4a4b9cc..3a4625f 100644 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -16,6 +16,7 @@ type App struct { ctx context.Context logger *logrus.Entry config *configuration.Config + wg *sync.WaitGroup domains map[string]domains.Domain domainsMutex sync.RWMutex @@ -118,3 +119,11 @@ func (a *App) StartDomains() error { return nil } + +func (a *App) RegisterGlobalWaitGroup(wg *sync.WaitGroup) { + a.wg = wg +} + +func (a *App) GetGlobalWaitGroup() *sync.WaitGroup { + return a.wg +} diff --git a/internal/domains/filesystem/errors.go b/internal/domains/filesystem/errors.go index 3039760..fbb1e3a 100644 --- a/internal/domains/filesystem/errors.go +++ b/internal/domains/filesystem/errors.go @@ -6,6 +6,7 @@ var ( ErrFilesystem = errors.New("filesystem") ErrConnectDependencies = errors.New("failed to connect dependencies") ErrFailedToPrepareDirectories = errors.New("failed to prepare directories") + ErrFailedToGetWaitGroup = errors.New("failed to get global waitgroup") ErrNoSource = errors.New("source does not exist") ErrFailedToCleanupDestination = errors.New("failed to clean up destination directory") ErrFailedToCreateDestinationDirectory = errors.New("failed to create destination directory") diff --git a/internal/domains/filesystem/filesystem.go b/internal/domains/filesystem/filesystem.go index 79c1968..290006f 100644 --- a/internal/domains/filesystem/filesystem.go +++ b/internal/domains/filesystem/filesystem.go @@ -58,9 +58,14 @@ func (f *FS) Start() error { return fmt.Errorf("%w: %w (%w)", ErrFilesystem, ErrFailedToPrepareDirectories, err) } - go func() { + wg := f.app.GetGlobalWaitGroup() + if wg == nil { + return fmt.Errorf("%w: %w (%s)", ErrFilesystem, ErrFailedToGetWaitGroup, "got nil waitgroup") + } + + wg.Go(func() { f.mount() - }() + }) return nil } diff --git a/internal/domains/filesystem/mount.go b/internal/domains/filesystem/mount.go index 837a407..5621965 100644 --- a/internal/domains/filesystem/mount.go +++ b/internal/domains/filesystem/mount.go @@ -43,10 +43,6 @@ func (f *FS) mount() { } defer server.Unmount() - select { - case <-f.app.Context().Done(): - return - default: - server.Wait() - } + <-f.app.Context().Done() + f.app.Logger().Debug("Application context cancelled, unmounting FUSE server...") }