Bladeren bron

Fix tail_f_producer when file is closed or unlinked

Mike Naberezny 10 jaren geleden
bovenliggende
commit
f90dd36e3a
2 gewijzigde bestanden met toevoegingen van 33 en 3 verwijderingen
  1. 3 2
      supervisor/http.py
  2. 30 1
      supervisor/tests/test_http.py

+ 3 - 2
supervisor/http.py

@@ -664,7 +664,7 @@ class tail_f_producer:
         self._follow()
         try:
             newsz = self._fsize()
-        except OSError:
+        except (OSError, ValueError):
             # file descriptor was closed
             return ''
         bytes_added = newsz - self.sz
@@ -689,7 +689,8 @@ class tail_f_producer:
     def _follow(self):
         try:
             ino = os.stat(self.filename)[stat.ST_INO]
-        except OSError:
+        except (OSError, ValueError):
+            # file was unlinked
             return
 
         if self.ino != ino: # log rotation occurred

+ 30 - 1
supervisor/tests/test_http.py

@@ -139,7 +139,17 @@ class TailFProducerTests(unittest.TestCase):
         result = producer.more()
         self.assertEqual(result, '==> File truncated <==\n')
 
-    def test_handle_more_follow(self):
+    def test_handle_more_fd_closed(self):
+        request = DummyRequest('/logtail/foo', None, None, None)
+        f = tempfile.NamedTemporaryFile()
+        f.write(as_bytes('a' * 80))
+        f.flush()
+        producer = self._makeOne(request, f.name, 80)
+        producer.file.close()
+        result = producer.more()
+        self.assertEqual(result, producer.more())
+
+    def test_handle_more_follow_file_recreated(self):
         request = DummyRequest('/logtail/foo', None, None, None)
         f = tempfile.NamedTemporaryFile()
         f.write('a' * 80)
@@ -157,6 +167,25 @@ class TailFProducerTests(unittest.TestCase):
             os.unlink(f2.name)
         self.assertEqual(result, 'b' * 80)
 
+    def test_handle_more_follow_file_gone(self):
+        request = DummyRequest('/logtail/foo', None, None, None)
+        filename = tempfile.mktemp()
+        with open(filename, 'wb') as f:
+            f.write(as_bytes('a' * 80))
+        try:
+            producer = self._makeOne(request, f.name, 80)
+        finally:
+            os.unlink(f.name)
+        result = producer.more()
+        self.assertEqual(result, as_bytes('a' * 80))
+        with open(filename, 'wb') as f:
+            f.write(as_bytes('b' * 80))
+        try:
+            result = producer.more() # should open in new file
+            self.assertEqual(result, as_bytes('b' * 80))
+        finally:
+             os.unlink(f.name)
+
 class DeferringChunkedProducerTests(unittest.TestCase):
     def _getTargetClass(self):
         from supervisor.http import deferring_chunked_producer