From 95675a89b75667a457e853fda28e6ce8fd53f223 Mon Sep 17 00:00:00 2001
From: Alexander Bus <busfromrus@gmail.com>
Date: Thu, 17 May 2018 23:29:55 +0700
Subject: [PATCH] Improve reading from the socket

Fixes #6
---
 cutelog/listener.py | 47 ++++++++++++++++++++++++++++-----------------
 setup.py            |  2 +-
 2 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/cutelog/listener.py b/cutelog/listener.py
index d01d376..dedac90 100644
--- a/cutelog/listener.py
+++ b/cutelog/listener.py
@@ -109,37 +109,48 @@ class LogConnection(QThread):
     def run(self):
         self.log.debug('Connection "{}" is starting'.format(self.name))
 
-        def wait_and_read(n_bytes, wait_ms):
-            "Convinience function that simplifies checking for stop events, etc."
-            if sock.bytesAvailable() == 0:
-                new_data = sock.waitForReadyRead(wait_ms)
-                if not new_data:
-                    return None
-            return sock.read(n_bytes)
+        def wait_and_read(n_bytes):
+            """
+            Convinience function that simplifies reading and checking for stop events, etc.
+            Returns a byte string of length n_bytes or None if socket needs to be closed.
+
+            """
+            data = b""
+            while len(data) < n_bytes:
+                if sock.bytesAvailable() == 0:
+                    new_data = sock.waitForReadyRead(100)  # wait for 100ms between read attempts
+                    if not new_data:
+                        if sock.state() != sock.ConnectedState or self.need_to_stop():
+                            return None
+                        else:
+                            continue
+                new_data = sock.read(n_bytes - len(data))
+                data += new_data
+            return data
 
         sock = QTcpSocket(None)
         sock.setSocketDescriptor(self.socketDescriptor)
         sock.waitForConnected()
 
         while True:
-            if sock.state() != sock.ConnectedState or self.need_to_stop():
-                self.log.debug('Connection "{}" is stopping'.format(self.name))
-                break
-            read_len = wait_and_read(4, 100)
+            read_len = wait_and_read(4)
             if not read_len:
-                continue
+                break
             read_len = struct.unpack(">L", read_len)[0]
 
-            if sock.bytesAvailable() == 0:
-                sock.waitForReadyRead()
-            data = sock.read(read_len)
+            data = wait_and_read(read_len)
             if not data:
-                continue
+                break
 
-            data = pickle.loads(data)
-            record = logging.makeLogRecord(data)
+            try:
+                data = pickle.loads(data)
+                record = logging.makeLogRecord(data)
+            except Exception as e:
+                self.log.error('Creating log record failed', exc_info=True)
+                continue
             self.new_record.emit(record)
 
+        self.log.debug('Connection "{}" is stopping'.format(self.name))
         sock.disconnectFromHost()
         sock.close()
         self.connection_finished.emit(self)
diff --git a/setup.py b/setup.py
index 20f1e56..e568cdb 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ from setuptools import setup
 from setuptools.command.install import install
 
 
-VERSION = '1.1.8'
+VERSION = '1.1.9'
 
 
 def build_qt_resources():
-- 
GitLab