wails/v3/internal/commands/watcher.go
Lea Anthony b0871c19e1
[v3] Fix: Vite server not cleaned up when build fails (#4436)
* fix: properly clean up Vite server when build fails

Ensures the Vite server process is terminated when a build fails
during 'wails3 dev', preventing port conflicts on subsequent runs.

Fixes #4403

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: add defer for watcher cleanup and tidy up returns

- Add defer cleanup() to ensure resources are always freed
- Remove manual cleanup in error path since defer handles it
- Simplify error handling for better maintainability

Addresses feedback on PR #4436

* fix: prevent channel deadlock in watcher cleanup

- Separate cleanup logic from channel notification
- cleanup() only stops the engine
- signalCleanup() handles both cleanup and channel notification
- Prevents deadlock when function exits normally

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-02 17:48:01 +10:00

65 lines
1.2 KiB
Go

package commands
import (
"github.com/atterpac/refresh/engine"
"github.com/wailsapp/wails/v3/internal/signal"
"gopkg.in/yaml.v3"
"os"
)
type WatcherOptions struct {
Config string `description:"The config file including path" default:"."`
}
func Watcher(options *WatcherOptions) error {
stopChan := make(chan struct{})
// Parse the config file
type devConfig struct {
Config engine.Config `yaml:"dev_mode"`
}
var devconfig devConfig
// Parse the config file
c, err := os.ReadFile(options.Config)
if err != nil {
return err
}
err = yaml.Unmarshal(c, &devconfig)
if err != nil {
return err
}
watcherEngine, err := engine.NewEngineFromConfig(devconfig.Config)
if err != nil {
return err
}
// Setup cleanup function that stops the engine
cleanup := func() {
watcherEngine.Stop()
}
defer cleanup()
// Signal handler needs to notify when to stop
signalCleanup := func() {
cleanup()
stopChan <- struct{}{}
}
signalHandler := signal.NewSignalHandler(signalCleanup)
signalHandler.ExitMessage = func(sig os.Signal) string {
return ""
}
signalHandler.Start()
// Start the engine
err = watcherEngine.Start()
if err != nil {
return err
}
<-stopChan
return nil
}