Skip to content

Commit b39f376

Browse files
torsmcopybara-github
authored andcommitted
Fix bug where the client would always exit ungracefully after receiving a signal
PiperOrigin-RevId: 870898716
1 parent 2053a93 commit b39f376

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

cmd/fleetspeak_client/fleetspeak_client.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"os"
88
"time"
99

10-
log "github.com/golang/glog"
1110
"google.golang.org/protobuf/encoding/prototext"
1211

1312
"github.com/google/fleetspeak/fleetspeak/src/client"
@@ -20,6 +19,7 @@ import (
2019
"github.com/google/fleetspeak/fleetspeak/src/client/socketservice"
2120
"github.com/google/fleetspeak/fleetspeak/src/client/stats"
2221
"github.com/google/fleetspeak/fleetspeak/src/client/stdinservice"
22+
"github.com/google/fleetspeak/fleetspeak/src/common/fscontext"
2323

2424
gpb "github.com/google/fleetspeak/fleetspeak/src/client/generic/proto/fleetspeak_client_generic"
2525
)
@@ -29,42 +29,34 @@ const stopTimeout = time.Minute
2929
var configFile = flag.String("config", "", "Client configuration file, required.")
3030

3131
func innerMain(ctx context.Context, cfgReloadSignals <-chan os.Signal) error {
32-
for {
33-
cl, err := createClient()
32+
for ctx.Err() == nil {
33+
ctx, cancel := entry.ContextWithSignals(ctx, cfgReloadSignals)
34+
err := runClient(ctx)
35+
cancel()
3436
if err != nil {
35-
return fmt.Errorf("error starting client: %v", err)
36-
}
37-
38-
select {
39-
case <-cfgReloadSignals:
40-
// We implement config reloading by tearing down the client and creating a
41-
// new one.
42-
log.Info("Config reload requested")
43-
time.AfterFunc(stopTimeout, func() {
44-
entry.ExitUngracefully(fmt.Errorf("client did not stop within %s", stopTimeout))
45-
})
46-
cl.Stop()
47-
continue
48-
case <-ctx.Done():
49-
// A timeout for process termination is handled higher up.
50-
cl.Stop()
51-
return nil
37+
return err
5238
}
5339
}
40+
return nil
5441
}
5542

56-
func createClient() (*client.Client, error) {
43+
func runClient(ctx context.Context) error {
44+
stop := fscontext.AfterDelayFunc(ctx, stopTimeout, func() {
45+
entry.ExitUngracefully(fmt.Errorf("client did not stop within %s", stopTimeout))
46+
})
47+
defer stop()
48+
5749
b, err := os.ReadFile(*configFile)
5850
if err != nil {
59-
return nil, fmt.Errorf("unable to read configuration file %q: %v", *configFile, err)
51+
return fmt.Errorf("unable to read configuration file %q: %v", *configFile, err)
6052
}
6153
cfgPB := &gpb.Config{}
6254
if err := prototext.Unmarshal(b, cfgPB); err != nil {
63-
return nil, fmt.Errorf("unable to parse configuration file %q: %v", *configFile, err)
55+
return fmt.Errorf("unable to parse configuration file %q: %v", *configFile, err)
6456
}
6557
cfg, err := generic.MakeConfiguration(cfgPB)
6658
if err != nil {
67-
return nil, fmt.Errorf("error in configuration file: %v", err)
59+
return fmt.Errorf("error in configuration file: %v", err)
6860
}
6961

7062
var com comms.Communicator
@@ -74,7 +66,7 @@ func createClient() (*client.Client, error) {
7466
com = &https.Communicator{}
7567
}
7668

77-
return client.New(
69+
cl, err := client.New(
7870
cfg,
7971
client.Components{
8072
ServiceFactories: map[string]service.Factory{
@@ -87,6 +79,15 @@ func createClient() (*client.Client, error) {
8779
Stats: stats.NoopCollector{},
8880
},
8981
)
82+
if err != nil {
83+
return fmt.Errorf("error creating client: %v", err)
84+
}
85+
86+
select {
87+
case <-ctx.Done():
88+
cl.Stop()
89+
}
90+
return nil
9091
}
9192

9293
func main() {

fleetspeak/src/client/entry/entry.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"context"
77
"os"
88
"time"
9+
10+
log "github.com/golang/glog"
911
)
1012

1113
// Timeout for shutting down gracefully.
@@ -22,3 +24,20 @@ const shutdownTimeout = 10 * time.Second
2224
// is requested. We use UNIX conventions here, the Windows layer can send a
2325
// [syscall.SIGHUP] when appropriate.
2426
type InnerMain func(ctx context.Context, cfgReloadSignals <-chan os.Signal) error
27+
28+
// ContextWithSignals returns a context that is canceled when a signal is
29+
// received.
30+
func ContextWithSignals(ctx context.Context, signals <-chan os.Signal) (context.Context, context.CancelFunc) {
31+
ctx, cancel := context.WithCancel(ctx)
32+
go func() {
33+
select {
34+
case si, ok := <-signals:
35+
if ok {
36+
log.Infof("Signal received: %v", si)
37+
cancel()
38+
}
39+
case <-ctx.Done():
40+
}
41+
}()
42+
return ctx, cancel
43+
}

0 commit comments

Comments
 (0)