@@ -222,51 +222,24 @@ func (r *runnableGroup) reconcile() {
222222
223223		// Start the runnable. 
224224		go  func (rn  * readyRunnable ) {
225- 			// If we return, the runnable ended cleanly 
226- 			// or returned an error to the channel. 
227- 			// 
228- 			// We should always decrement the WaitGroup here. 
229- 			defer  r .wg .Done ()
230- 
231- 			// Track the ready check in the same WaitGroup to prevent goroutine leaks 
232- 			done  :=  make (chan  struct {})
233- 
234- 			// Launch the ready check but make sure it doesn't outlive this goroutine 
235225			go  func () {
236- 				defer  close (done )
237226				if  rn .Check (r .ctx ) {
238227					if  rn .signalReady  {
239- 						// Use non-blocking send to avoid leaking this goroutine if the channel is never read 
240- 						select  {
241- 						case  r .startReadyCh  <-  rn :
242- 							// Successfully sent 
243- 						case  <- r .ctx .Done ():
244- 							// Context canceled, exit without blocking 
245- 						}
228+ 						r .startReadyCh  <-  rn 
246229					}
247230				}
248231			}()
249232
250- 			// Start the runnable. 
251- 			err  :=  rn .Start (r .ctx )
252- 
253- 			// Now that the runnable is done, clean up the ready check goroutine if still running 
254- 			select  {
255- 			case  <- done :
256- 				// Ready check already completed, nothing to do 
257- 			case  <- r .ctx .Done ():
258- 				// Context was canceled, ready check should exit soon 
259- 			}
233+             // If we return, the runnable ended cleanly 
234+ 			// or returned an error to the channel. 
235+ 			// 
236+ 			// We should always decrement the WaitGroup here. 
237+ 			defer  r .wg .Done ()
260238
261- 			// Send any error from the runnable 
262- 			if  err  !=  nil  {
263- 				select  {
264- 				case  r .errChan  <-  err :
265- 					// Error sent successfully 
266- 				default :
267- 					// Channel full or closed, can't send the error 
268- 				}
269- 			}
239+ 			// Start the runnable. 
240+             if  err  :=  rn .Start (r .ctx ); err  !=  nil  {
241+                 r .errChan  <-  err 
242+             }
270243		}(runnable )
271244	}
272245}
@@ -324,13 +297,18 @@ func (r *runnableGroup) Add(rn Runnable, ready runnableCheck) error {
324297// StopAndWait waits for all the runnables to finish before returning. 
325298func  (r  * runnableGroup ) StopAndWait (ctx  context.Context ) {
326299	r .stopOnce .Do (func () {
300+         // Close the reconciler channel once we're done. 
301+ 		defer  func () {
302+ 			r .stop .Lock ()
303+ 			close (r .ch )
304+ 			r .stop .Unlock ()
305+ 		}()
306+ 
327307		_  =  r .Start (ctx )
328308		r .stop .Lock ()
329309		// Store the stopped variable so we don't accept any new 
330310		// runnables for the time being. 
331311		r .stopped  =  true 
332- 		// Close the channel to signal the reconcile goroutine to exit 
333- 		close (r .ch )
334312		r .stop .Unlock ()
335313
336314		// Cancel the internal channel. 
0 commit comments