Browse Source

Handle thread interruption when enqueueing log message (#4336)

Handle thread interruption when enqueueing log message
Tobias Kaminsky 5 years ago
parent
commit
c32ca050a3

+ 11 - 5
src/main/java/com/nextcloud/client/logger/LoggerImpl.kt

@@ -101,11 +101,17 @@ internal class LoggerImpl(
     }
     }
 
 
     private fun enqueue(level: Level, tag: String, message: String) {
     private fun enqueue(level: Level, tag: String, message: String) {
-        val entry = LogEntry(timestamp = clock.currentDate, level = level, tag = tag, message = message)
-        val enqueued = eventQueue.offer(entry, 1, TimeUnit.SECONDS)
-        if (!enqueued) {
-            missedLogs.set(true)
-            missedLogsCount.incrementAndGet()
+        try {
+            val entry = LogEntry(timestamp = clock.currentDate, level = level, tag = tag, message = message)
+            val enqueued = eventQueue.offer(entry, 1, TimeUnit.SECONDS)
+            if (!enqueued) {
+                missedLogs.set(true)
+                missedLogsCount.incrementAndGet()
+            }
+        } catch (ex: InterruptedException) {
+            // since interrupted flag is consumed now, we need to re-set the flag so
+            // the caller can continue handling the thread interruption in it's own way
+            Thread.currentThread().interrupt()
         }
         }
     }
     }
 
 

+ 31 - 0
src/test/java/com/nextcloud/client/logger/LoggerTest.kt

@@ -35,6 +35,7 @@ import com.nhaarman.mockitokotlin2.whenever
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
 import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Before
 import org.junit.Test
 import org.junit.Test
@@ -285,4 +286,34 @@ class LoggerTest {
         assertEquals(0, loaded.lines.size)
         assertEquals(0, loaded.lines.size)
         assertEquals(0L, loaded.logSize)
         assertEquals(0L, loaded.logSize)
     }
     }
+
+    @Test
+    fun `thread interruption is handled while posting log message`() {
+        Thread {
+            val callerThread = Thread.currentThread()
+            // GIVEN
+            //      logger is running
+            //      caller thread is interrupted
+            logger.start()
+            callerThread.interrupt()
+
+            // WHEN
+            //      message is logged on interrupted thread
+            var loggerException: Throwable? = null
+            try {
+                logger.d("test", "test")
+            } catch (ex: Throwable) {
+                loggerException = ex
+            }
+
+            // THEN
+            //      message post is gracefully skipped
+            //      thread interruption flag is not cleared
+            assertNull(loggerException)
+            assertTrue("Expected current thread to stay interrupted", callerThread.isInterrupted)
+        }.apply {
+            start()
+            join(3000)
+        }
+    }
 }
 }