mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Prevent timer leaks in Workerpool and others (#11333)
There is a potential memory leak in `Workerpool` due to the intricacies of `time.Timer` stopping. Whenever a `time.Timer` is `Stop`ped its channel must be cleared using a `select` if the result of the `Stop()` is `false`. Unfortunately in `Workerpool` these were checked the wrong way round. However, there were a few other places that were not being checked. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		| @@ -12,6 +12,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
|  | ||||
| // WrappedQueueType is the type for a wrapped delayed starting queue | ||||
| @@ -88,7 +89,7 @@ func (q *delayedStarter) setInternal(atShutdown func(context.Context, func()), h | ||||
| 			t := time.NewTimer(sleepTime) | ||||
| 			select { | ||||
| 			case <-ctx.Done(): | ||||
| 				t.Stop() | ||||
| 				util.StopTimer(t) | ||||
| 			case <-t.C: | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
|  | ||||
| // WorkerPool represent a dynamically growable worker pool for a | ||||
| @@ -92,12 +93,7 @@ func (p *WorkerPool) pushBoost(data Data) { | ||||
| 		p.lock.Unlock() | ||||
| 		select { | ||||
| 		case p.dataChan <- data: | ||||
| 			if timer.Stop() { | ||||
| 				select { | ||||
| 				case <-timer.C: | ||||
| 				default: | ||||
| 				} | ||||
| 			} | ||||
| 			util.StopTimer(timer) | ||||
| 		case <-timer.C: | ||||
| 			p.lock.Lock() | ||||
| 			if p.blockTimeout > ourTimeout || (p.numberOfWorkers > p.maxNumberOfWorkers && p.maxNumberOfWorkers >= 0) { | ||||
| @@ -353,12 +349,7 @@ func (p *WorkerPool) doWork(ctx context.Context) { | ||||
| 			timer := time.NewTimer(delay) | ||||
| 			select { | ||||
| 			case <-ctx.Done(): | ||||
| 				if timer.Stop() { | ||||
| 					select { | ||||
| 					case <-timer.C: | ||||
| 					default: | ||||
| 					} | ||||
| 				} | ||||
| 				util.StopTimer(timer) | ||||
| 				if len(data) > 0 { | ||||
| 					log.Trace("Handling: %d data, %v", len(data), data) | ||||
| 					p.handle(data...) | ||||
| @@ -367,12 +358,7 @@ func (p *WorkerPool) doWork(ctx context.Context) { | ||||
| 				log.Trace("Worker shutting down") | ||||
| 				return | ||||
| 			case datum, ok := <-p.dataChan: | ||||
| 				if timer.Stop() { | ||||
| 					select { | ||||
| 					case <-timer.C: | ||||
| 					default: | ||||
| 					} | ||||
| 				} | ||||
| 				util.StopTimer(timer) | ||||
| 				if !ok { | ||||
| 					// the dataChan has been closed - we should finish up: | ||||
| 					if len(data) > 0 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user