mirror of
https://github.com/containous/traefik.git
synced 2025-06-01 17:05:36 +03:00
Merge 0c0ae8371e78a5ae9364ba3992944bb87297cbf3 into 4790e4910ff5034b1b5d43aa95eea0d862589fd3
This commit is contained in:
commit
1d67a8a0a8
@ -49,6 +49,9 @@ import (
|
||||
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||
"github.com/traefik/traefik/v3/pkg/types"
|
||||
"github.com/traefik/traefik/v3/pkg/version"
|
||||
wsvc "golang.org/x/sys/windows/svc"
|
||||
"github.com/traefik/traefik/v3/pkg/winsvc"
|
||||
winruntime "runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -124,6 +127,9 @@ func runCmd(staticConfiguration *static.Configuration) error {
|
||||
}
|
||||
|
||||
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
ctx, cancel := setupWindowsServiceCancellation(ctx)
|
||||
defer cancel()
|
||||
|
||||
if staticConfiguration.Ping != nil {
|
||||
staticConfiguration.Ping.WithContext(ctx)
|
||||
@ -168,6 +174,37 @@ func runCmd(staticConfiguration *static.Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupWindowsServiceCancellation(ctx context.Context) (context.Context, context.CancelFunc) {
|
||||
// If not on Windows, return a cancellable context without additional logic
|
||||
if winruntime.GOOS != "windows" {
|
||||
return context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
isService, err := wsvc.IsWindowsService()
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to determine if running as a Windows Service")
|
||||
isService = false // Default to CMD mode if unsure
|
||||
}
|
||||
|
||||
if !isService {
|
||||
log.Info().Msg("Running in CMD mode, skipping Windows Service cancellation setup.")
|
||||
return context.WithCancel(ctx) // No-op but still valid
|
||||
}
|
||||
|
||||
// Windows Service mode: Create a cancellable context
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
// Listen for Windows Service stop signal
|
||||
go func() {
|
||||
<-winsvc.ChanExit
|
||||
log.Info().Msg("Received Windows Service stop signal, shutting down...")
|
||||
cancel()
|
||||
}()
|
||||
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
|
||||
func setupServer(staticConfiguration *static.Configuration) (*server.Server, error) {
|
||||
providerAggregator := aggregator.NewProviderAggregator(*staticConfiguration.Providers)
|
||||
|
||||
|
3
pkg/winsvc/service.go
Normal file
3
pkg/winsvc/service.go
Normal file
@ -0,0 +1,3 @@
|
||||
package winsvc
|
||||
|
||||
var ChanExit = make(chan int, 1) // Buffered channel to prevent blocking
|
46
pkg/winsvc/service_windows.go
Normal file
46
pkg/winsvc/service_windows.go
Normal file
@ -0,0 +1,46 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winsvc
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog/log"
|
||||
wsvc "golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
type serviceWindows struct{}
|
||||
|
||||
func init() {
|
||||
isService, err := wsvc.IsWindowsService()
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Failed to determine if running as a Windows Service")
|
||||
return
|
||||
}
|
||||
if !isService {
|
||||
log.Info().Msg("Running in CMD mode, skipping Windows Service setup.")
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
log.Info().Msg("Starting Traefik as a Windows Service")
|
||||
err := wsvc.Run("traefik", serviceWindows{})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to run Windows Service")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (serviceWindows) Execute(args []string, r <-chan wsvc.ChangeRequest, s chan<- wsvc.Status) (svcSpecificEC bool, exitCode uint32) {
|
||||
const accCommands = wsvc.AcceptStop | wsvc.AcceptShutdown
|
||||
s <- wsvc.Status{State: wsvc.Running, Accepts: accCommands}
|
||||
for {
|
||||
c := <-r
|
||||
switch c.Cmd {
|
||||
case wsvc.Interrogate:
|
||||
s <- c.CurrentStatus
|
||||
case wsvc.Stop, wsvc.Shutdown:
|
||||
s <- wsvc.Status{State: wsvc.StopPending}
|
||||
close(ChanExit) // Close channel safely
|
||||
return false, 0
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user