Wed, 24 Apr 2024 15:16:12 +0200
Made the various JSON based client-server interface a bit more resilient against slow data transfer.
--- a/src/eric7/Debugger/DebuggerInterfacePython.py Wed Apr 24 15:15:33 2024 +0200 +++ b/src/eric7/Debugger/DebuggerInterfacePython.py Wed Apr 24 15:16:12 2024 +0200 @@ -1404,8 +1404,15 @@ @param sock reference to the socket to read data from @type QTcpSocket """ + headerSize = struct.calcsize(b"!II") + while sock and sock.bytesAvailable(): - header = sock.read(struct.calcsize(b"!II")) + now = time.monotonic() + while sock.bytesAvailable() < headerSize: + sock.waitForReadyRead(50) + if time.monotonic() - now > 2.0: # 2 seconds timeout + return + header = sock.read(headerSize) length, datahash = struct.unpack(b"!II", header) data = bytearray()
--- a/src/eric7/EricNetwork/EricJsonServer.py Wed Apr 24 15:15:33 2024 +0200 +++ b/src/eric7/EricNetwork/EricJsonServer.py Wed Apr 24 15:16:12 2024 +0200 @@ -10,6 +10,7 @@ import contextlib import json import struct +import time import zlib from PyQt6.QtCore import ( @@ -149,6 +150,8 @@ @param idString id of the connection @type str """ + headerSize = struct.calcsize(b"!II") + if idString: try: connection = self.__connections[idString] @@ -158,15 +161,26 @@ connection = self.__connection while connection and connection.bytesAvailable(): - header = connection.read(struct.calcsize(b"!II")) + now = time.monotonic() + while connection.bytesAvailable() < headerSize: + connection.waitForReadyRead(50) + if time.monotonic() - now > 2.0: # 2 seconds timeout + return + header = connection.read(headerSize) length, datahash = struct.unpack(b"!II", header) data = bytearray() + now = time.monotonic() while len(data) < length: maxSize = length - len(data) if connection.bytesAvailable() < maxSize: connection.waitForReadyRead(50) - data += connection.read(maxSize) + newData = connection.read(maxSize) + if newData: + data += newData + else: + if time.monotonic() - now > 2.0: # 2 seconds timeout + break if zlib.adler32(data) & 0xFFFFFFFF != datahash: # corrupted data -> discard and continue
--- a/src/eric7/Utilities/BackgroundService.py Wed Apr 24 15:15:33 2024 +0200 +++ b/src/eric7/Utilities/BackgroundService.py Wed Apr 24 15:16:12 2024 +0200 @@ -13,8 +13,8 @@ import os import struct import sys - -from zlib import adler32 +import time +import zlib from PyQt6.QtCore import QProcess, QThread, QTimer, pyqtSignal from PyQt6.QtNetwork import QHostAddress, QTcpServer @@ -175,7 +175,7 @@ packedData = json.dumps([fx, fn, data]) packedData = bytes(packedData, "utf-8") header = struct.pack( - b"!II", len(packedData), adler32(packedData) & 0xFFFFFFFF + b"!II", len(packedData), zlib.adler32(packedData) & 0xFFFFFFFF ) connection.write(header) connection.write(b"JOB ") # 6 character message type @@ -189,22 +189,35 @@ @type str @exception RuntimeError raised if hashes don't match """ + headerSize = struct.calcsize(b"!II") + data = "" fx = "" connection = self.connections[lang] - while connection.bytesAvailable(): - header = connection.read(struct.calcsize(b"!II")) + while connection and connection.bytesAvailable(): + now = time.monotonic() + while connection.bytesAvailable() < headerSize: + connection.waitForReadyRead(50) + if time.monotonic() - now > 2.0: # 2 seconds timeout + return + header = connection.read(headerSize) length, datahash = struct.unpack(b"!II", header) packedData = b"" + now = time.monotonic() while len(packedData) < length: maxSize = length - len(packedData) if connection.bytesAvailable() < maxSize: connection.waitForReadyRead(50) - packedData += connection.read(maxSize) + newData = connection.read(maxSize) + if newData: + packedData += newData + else: + if time.monotonic() - now > 2.0: # 2 seconds timeout + break - if adler32(packedData) & 0xFFFFFFFF != datahash: + if zlib.adler32(packedData) & 0xFFFFFFFF != datahash: raise RuntimeError("Hashes not equal") packedData = packedData.decode("utf-8") # "check" if is's a tuple of 3 values