From 4dbf645bf76bfd288a39d01e07b67ff6a0b52510 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Thu, 12 Jun 2025 09:35:57 -0700 Subject: [PATCH] command: prevent panic on graceful shutdown (#26018) When performing a graceful shutdown a channel is used to wait for the agent to leave. The channel is closed when the agent leaves successfully, but it also is closed within a deferral. If the agent successfully leaves and closes the channel, a panic will occur when the channel is closed the second time within the deferral. To prevent this from occurring, the channel closing is wrapped within a `OnceFunc` so the channel is only closed once. --- .changelog/26018.txt | 3 +++ command/agent/command.go | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changelog/26018.txt diff --git a/.changelog/26018.txt b/.changelog/26018.txt new file mode 100644 index 000000000..c8f356843 --- /dev/null +++ b/.changelog/26018.txt @@ -0,0 +1,3 @@ +```release-note:bug +agent: Fixed a bug to prevent a possible panic during graceful shutdown +``` diff --git a/command/agent/command.go b/command/agent/command.go index 0ffc96c7d..b6b541f54 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -16,6 +16,7 @@ import ( "sort" "strconv" "strings" + "sync" "syscall" "time" @@ -983,7 +984,8 @@ func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) sdNotify(sdSock, sdStopping) gracefulCh := make(chan struct{}) - defer close(gracefulCh) + gracefulClose := sync.OnceFunc(func() { close(gracefulCh) }) + defer gracefulClose() timeout := gracefulTimeout @@ -1002,7 +1004,7 @@ func (c *Command) terminateGracefully(signalCh chan os.Signal, sdSock io.Writer) c.Ui.Error(fmt.Sprintf("Error: %s", err)) return } - close(gracefulCh) + gracefulClose() }() delay := time.NewTimer(timeout)