Fix SoundQueue memory leak causing system lockups
Added bounded queue protection to prevent infinite memory growth during high-latency audio processing. Limits queue to 250 frames (~5 seconds) with conservative frame dropping to minimize stuttering while preventing runaway memory usage that was causing 4GB+ leaks and system freezes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		| @@ -19,6 +19,11 @@ class SoundQueue: | |||||||
|         self.queue = deque() |         self.queue = deque() | ||||||
|         self.start_sequence = None |         self.start_sequence = None | ||||||
|         self.start_time = None |         self.start_time = None | ||||||
|  |          | ||||||
|  |         # Prevent memory leaks from unbounded queue growth | ||||||
|  |         # Limit to ~5 seconds of audio at 20ms per frame = 250 frames max | ||||||
|  |         # More aggressive limit to reduce stuttering from dropped frames | ||||||
|  |         self.max_queue_size = 250 | ||||||
|  |  | ||||||
|         self.receive_sound = True |         self.receive_sound = True | ||||||
|          |          | ||||||
| @@ -59,6 +64,17 @@ class SoundQueue: | |||||||
|             newsound = SoundChunk(pcm, sequence, len(pcm), calculated_time, type, target) |             newsound = SoundChunk(pcm, sequence, len(pcm), calculated_time, type, target) | ||||||
|  |  | ||||||
|             if not self.mumble_object.callbacks.get_callback(PYMUMBLE_CLBK_SOUNDRECEIVED): |             if not self.mumble_object.callbacks.get_callback(PYMUMBLE_CLBK_SOUNDRECEIVED): | ||||||
|  |                 # Prevent memory leak from unbounded queue growth | ||||||
|  |                 if len(self.queue) >= self.max_queue_size: | ||||||
|  |                     # Remove oldest frames to make room - these are likely stale anyway | ||||||
|  |                     # Drop frames more conservatively to minimize stuttering | ||||||
|  |                     dropped = 0 | ||||||
|  |                     while len(self.queue) >= self.max_queue_size * 0.8:  # Drop to 80% capacity | ||||||
|  |                         self.queue.pop() | ||||||
|  |                         dropped += 1 | ||||||
|  |                     if dropped > 10:  # Only warn for significant drops | ||||||
|  |                         self.mumble_object.Log.warning(f"SoundQueue overflow: dropped {dropped} stale audio frames") | ||||||
|  |                  | ||||||
|                 self.queue.appendleft(newsound) |                 self.queue.appendleft(newsound) | ||||||
|  |  | ||||||
|                 if len(self.queue) > 1 and self.queue[0].time < self.queue[1].time: |                 if len(self.queue) > 1 and self.queue[0].time < self.queue[1].time: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user