- Add package documentation for app, app_common, import, app_windows, and testutil files - Include author attribution (xfy)
120 lines
2.5 KiB
Go
120 lines
2.5 KiB
Go
//go:build windows
|
||
|
||
// Windows lacks POSIX signals (SIGUSR1, SIGUSR2, SIGHUP, SIGQUIT);
|
||
// this file provides stub implementations for those Unix-specific signals.
|
||
// Package app 提供 Lolly 应用程序的生命周期管理和命令行入口。
|
||
//
|
||
// 包含 Windows 平台特定的应用逻辑。
|
||
//
|
||
// 作者:xfy
|
||
package app
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
"rua.plus/lolly/internal/server"
|
||
)
|
||
|
||
// Run starts the application: loads config, creates servers, and handles signals (Windows version).
|
||
func (a *App) Run() int {
|
||
if err := a.loadAndValidateConfig(); err != nil {
|
||
return 1
|
||
}
|
||
|
||
a.initVariables()
|
||
a.logServerAddresses()
|
||
a.initResolver()
|
||
a.initServer()
|
||
a.initStreamServers()
|
||
a.initHTTP3()
|
||
a.initHTTP2()
|
||
|
||
a.upgradeMgr = server.NewUpgradeManager(a.srv)
|
||
if a.pidFile != "" {
|
||
a.upgradeMgr.SetPidFile(a.pidFile)
|
||
_ = a.upgradeMgr.WritePid()
|
||
}
|
||
|
||
sigChan := make(chan os.Signal, 1)
|
||
a.setupSignalHandlers(sigChan)
|
||
|
||
errChan := make(chan error, 1)
|
||
go func() {
|
||
a.logger.LogStartup("Starting HTTP server", nil)
|
||
if err := a.srv.Start(); err != nil {
|
||
errChan <- err
|
||
}
|
||
}()
|
||
|
||
sigintCount := 0
|
||
|
||
for {
|
||
select {
|
||
case err := <-errChan:
|
||
a.logger.Error().Err(err).Msg("Server failed to start")
|
||
return 1
|
||
case sig := <-sigChan:
|
||
if sig == syscall.SIGINT {
|
||
sigintCount++
|
||
if sigintCount >= 3 {
|
||
a.logger.LogShutdown("Received 3 SIGINT, forcing exit")
|
||
return 1
|
||
}
|
||
}
|
||
if !a.handleSignal(sig) {
|
||
a.logger.LogShutdown("Server stopped")
|
||
return 0
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (a *App) setupSignalHandlers(sigChan chan<- os.Signal) {
|
||
signal.Notify(sigChan,
|
||
syscall.SIGTERM,
|
||
syscall.SIGINT,
|
||
)
|
||
}
|
||
|
||
// handleSignal returns false to indicate the app should exit (Windows version).
|
||
func (a *App) handleSignal(sig os.Signal) bool {
|
||
switch sig {
|
||
case syscall.SIGTERM, syscall.SIGINT:
|
||
timeout := a.cfg.Shutdown.FastTimeout
|
||
if timeout <= 0 {
|
||
timeout = 5 * time.Second
|
||
}
|
||
a.logger.LogSignal(sigName(sig.(syscall.Signal)), "Stopping server")
|
||
a.shutdownHTTP2()
|
||
a.shutdownHTTP3()
|
||
_ = a.srv.StopWithTimeout(timeout)
|
||
return false
|
||
default:
|
||
a.logger.Info().Str("signal", sig.String()).Msg("Received signal (ignored on Windows)")
|
||
return true
|
||
}
|
||
}
|
||
|
||
func (a *App) reloadConfig() {
|
||
// Windows stub - functionality limited
|
||
}
|
||
|
||
func (a *App) gracefulUpgrade() {
|
||
a.logger.Info().Msg("Graceful upgrade is not supported on Windows")
|
||
}
|
||
|
||
func sigName(sig syscall.Signal) string {
|
||
switch sig {
|
||
case syscall.SIGTERM:
|
||
return "SIGTERM"
|
||
case syscall.SIGINT:
|
||
return "SIGINT"
|
||
default:
|
||
return fmt.Sprintf("Signal(%d)", sig)
|
||
}
|
||
}
|