From 8eefe2af45f55f470e427ad30eb1aa316ec8cb73 Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Sat, 18 Jun 2022 03:33:13 +0100
Subject: [PATCH] Empty log queue on flush and close (#19994)

* Empty log queue on flush and close

It is possible for log events to remain in the buffer off the multichannelledlog
and thus not be logged despite close or flush.

This PR simply adds a function to empty the queue before closing or flushing.
(Except when the logger is paused.)

Reference #19982

Signed-off-by: Andrew Thornton <art27@cantab.net>

* and do similar for ChannelledLog

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 modules/log/event.go | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/modules/log/event.go b/modules/log/event.go
index f66ecd179b..41bb241da8 100644
--- a/modules/log/event.go
+++ b/modules/log/event.go
@@ -89,8 +89,10 @@ func (l *ChannelledLog) Start() {
 				l.closeLogger()
 				return
 			}
+			l.emptyQueue()
 			l.loggerProvider.Flush()
 		case <-l.close:
+			l.emptyQueue()
 			l.closeLogger()
 			return
 		}
@@ -111,6 +113,20 @@ func (l *ChannelledLog) LogEvent(event *Event) error {
 	}
 }
 
+func (l *ChannelledLog) emptyQueue() bool {
+	for {
+		select {
+		case event, ok := <-l.queue:
+			if !ok {
+				return false
+			}
+			l.loggerProvider.LogEvent(event)
+		default:
+			return true
+		}
+	}
+}
+
 func (l *ChannelledLog) closeLogger() {
 	l.loggerProvider.Flush()
 	l.loggerProvider.Close()
@@ -345,18 +361,41 @@ func (m *MultiChannelledLog) Start() {
 				m.closeLoggers()
 				return
 			}
+			m.emptyQueue()
 			m.rwmutex.RLock()
 			for _, logger := range m.loggers {
 				logger.Flush()
 			}
 			m.rwmutex.RUnlock()
 		case <-m.close:
+			m.emptyQueue()
 			m.closeLoggers()
 			return
 		}
 	}
 }
 
+func (m *MultiChannelledLog) emptyQueue() bool {
+	for {
+		select {
+		case event, ok := <-m.queue:
+			if !ok {
+				return false
+			}
+			m.rwmutex.RLock()
+			for _, logger := range m.loggers {
+				err := logger.LogEvent(event)
+				if err != nil {
+					fmt.Println(err)
+				}
+			}
+			m.rwmutex.RUnlock()
+		default:
+			return true
+		}
+	}
+}
+
 // LogEvent logs an event to this MultiChannelledLog
 func (m *MultiChannelledLog) LogEvent(event *Event) error {
 	select {