@@ -52,10 +52,12 @@ type RegistrationHandler struct {
52
52
// This is necessary because it implements APIs which don't
53
53
// provide a context.
54
54
backgroundCtx context.Context
55
+ cancel func (err error )
55
56
kubeClient kubernetes.Interface
56
57
getNode func () (* v1.Node , error )
57
58
wipingDelay time.Duration
58
59
60
+ wg sync.WaitGroup
59
61
mutex sync.Mutex
60
62
61
63
// pendingWipes maps a plugin name to a cancel function for
@@ -76,9 +78,15 @@ var _ cache.PluginHandler = &RegistrationHandler{}
76
78
// If a kubeClient is provided, then it synchronizes ResourceSlices
77
79
// with the resource information provided by plugins.
78
80
func NewRegistrationHandler (kubeClient kubernetes.Interface , getNode func () (* v1.Node , error ), wipingDelay time.Duration ) * RegistrationHandler {
81
+ // The context and thus logger should come from the caller.
82
+ return newRegistrationHandler (context .TODO (), kubeClient , getNode , wipingDelay )
83
+ }
84
+
85
+ func newRegistrationHandler (ctx context.Context , kubeClient kubernetes.Interface , getNode func () (* v1.Node , error ), wipingDelay time.Duration ) * RegistrationHandler {
86
+ ctx , cancel := context .WithCancelCause (ctx )
79
87
handler := & RegistrationHandler {
80
- // The context and thus logger should come from the caller.
81
- backgroundCtx : klog . NewContext ( context . TODO (), klog . LoggerWithName ( klog . TODO (), "DRA registration handler" )) ,
88
+ backgroundCtx : klog . NewContext ( ctx , klog . LoggerWithName ( klog . FromContext ( ctx ), "DRA registration handler" )),
89
+ cancel : cancel ,
82
90
kubeClient : kubeClient ,
83
91
getNode : getNode ,
84
92
wipingDelay : wipingDelay ,
@@ -92,13 +100,24 @@ func NewRegistrationHandler(kubeClient kubernetes.Interface, getNode func() (*v1
92
100
// to start up.
93
101
//
94
102
// This has to run in the background.
95
- logger := klog .LoggerWithName (klog .FromContext (handler .backgroundCtx ), "startup" )
96
- ctx := klog .NewContext (handler .backgroundCtx , logger )
97
- go handler .wipeResourceSlices (ctx , 0 /* no delay */ , "" /* all drivers */ )
103
+ handler .wg .Add (1 )
104
+ go func () {
105
+ defer handler .wg .Done ()
106
+
107
+ logger := klog .LoggerWithName (klog .FromContext (handler .backgroundCtx ), "startup" )
108
+ ctx := klog .NewContext (handler .backgroundCtx , logger )
109
+ handler .wipeResourceSlices (ctx , 0 /* no delay */ , "" /* all drivers */ )
110
+ }()
98
111
99
112
return handler
100
113
}
101
114
115
+ // Stop cancels any remaining background activities and blocks until all goroutines have stopped.
116
+ func (h * RegistrationHandler ) Stop () {
117
+ h .cancel (errors .New ("Stop was called" ))
118
+ h .wg .Wait ()
119
+ }
120
+
102
121
// wipeResourceSlices deletes ResourceSlices of the node, optionally just for a specific driver.
103
122
// Wiping will delay for a while and can be canceled by canceling the context.
104
123
func (h * RegistrationHandler ) wipeResourceSlices (ctx context.Context , delay time.Duration , driver string ) {
@@ -291,7 +310,9 @@ func (h *RegistrationHandler) DeRegisterPlugin(pluginName, endpoint string) {
291
310
}
292
311
h .pendingWipes [pluginName ] = & cancel
293
312
313
+ h .wg .Add (1 )
294
314
go func () {
315
+ defer h .wg .Done ()
295
316
defer func () {
296
317
h .mutex .Lock ()
297
318
defer h .mutex .Unlock ()
0 commit comments