@@ -5,12 +5,16 @@ import (
5
5
"fmt"
6
6
"net"
7
7
"os"
8
+ "os/signal"
9
+ "syscall"
10
+ "time"
8
11
9
12
"github.com/spf13/cobra"
10
13
11
14
"github.com/stacklok/toolhive/pkg/container"
12
15
"github.com/stacklok/toolhive/pkg/groups"
13
16
"github.com/stacklok/toolhive/pkg/logger"
17
+ "github.com/stacklok/toolhive/pkg/process"
14
18
"github.com/stacklok/toolhive/pkg/runner"
15
19
"github.com/stacklok/toolhive/pkg/workloads"
16
20
)
@@ -77,6 +81,27 @@ func init() {
77
81
AddOIDCFlags (runCmd )
78
82
}
79
83
84
+ func cleanupAndWait (workloadManager workloads.Manager , name string , cancel context.CancelFunc , errCh <- chan error ) {
85
+ cleanupCtx , cleanupCancel := context .WithTimeout (context .Background (), 30 * time .Second )
86
+ defer cleanupCancel ()
87
+
88
+ group , err := workloadManager .DeleteWorkloads (cleanupCtx , []string {name })
89
+ if err != nil {
90
+ logger .Warnf ("Failed to delete workload %q: %v" , name , err )
91
+ } else if group != nil {
92
+ if err := group .Wait (); err != nil {
93
+ logger .Warnf ("DeleteWorkloads group error for %q: %v" , name , err )
94
+ }
95
+ }
96
+
97
+ cancel ()
98
+ select {
99
+ case <- errCh :
100
+ case <- time .After (5 * time .Second ):
101
+ logger .Warnf ("Timeout waiting for workload to stop" )
102
+ }
103
+ }
104
+
80
105
func runCmdFunc (cmd * cobra.Command , args []string ) error {
81
106
ctx := cmd .Context ()
82
107
@@ -107,6 +132,8 @@ func runCmdFunc(cmd *cobra.Command, args []string) error {
107
132
workloadName = serverOrImage
108
133
}
109
134
135
+ isForeground := runFlags .Foreground
136
+
110
137
if runFlags .Group != "" {
111
138
groupManager , err := groups .NewManager ()
112
139
if err != nil {
@@ -145,18 +172,35 @@ func runCmdFunc(cmd *cobra.Command, args []string) error {
145
172
}
146
173
workloadManager := workloads .NewManagerFromRuntime (rt )
147
174
148
- if runFlags .Foreground {
149
- err = workloadManager .RunWorkload (ctx , runnerConfig )
150
- } else {
151
- // Run the workload in detached mode
152
- err = workloadManager .RunWorkloadDetached (ctx , runnerConfig )
153
- }
154
- if err != nil {
155
- return err
175
+ if isForeground {
176
+ return runForeground (ctx , workloadManager , runnerConfig )
156
177
}
178
+ return workloadManager .RunWorkloadDetached (ctx , runnerConfig )
179
+ }
157
180
158
- return nil
181
+ func runForeground (ctx context.Context , workloadManager workloads.Manager , runnerConfig * runner.RunConfig ) error {
182
+ ctx , cancel := context .WithCancel (ctx )
183
+ defer cancel ()
159
184
185
+ sigCh := make (chan os.Signal , 1 )
186
+ signal .Notify (sigCh , os .Interrupt , syscall .SIGTERM )
187
+ defer signal .Stop (sigCh )
188
+
189
+ errCh := make (chan error , 1 )
190
+ go func () {
191
+ errCh <- workloadManager .RunWorkload (ctx , runnerConfig )
192
+ }()
193
+
194
+ select {
195
+ case sig := <- sigCh :
196
+ if ! process .IsDetached () {
197
+ logger .Infof ("Received signal: %v, stopping server %q" , sig , runnerConfig .BaseName )
198
+ cleanupAndWait (workloadManager , runnerConfig .BaseName , cancel , errCh )
199
+ }
200
+ return nil
201
+ case err := <- errCh :
202
+ return err
203
+ }
160
204
}
161
205
162
206
// parseCommandArguments processes command-line arguments to find everything after the -- separator
0 commit comments