1
0
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:
ahaenggli 2025-05-25 09:53:58 +00:00 committed by GitHub
commit 1d67a8a0a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 86 additions and 0 deletions

View File

@ -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
View File

@ -0,0 +1,3 @@
package winsvc
var ChanExit = make(chan int, 1) // Buffered channel to prevent blocking

View 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
}
}
}