Handle empty reads as closed connections

When the new Opendev 3.2 Gerrit closes the SSH connection, gerritlib
goes into a hard loop.  Either this has never really worked, or our
new version of gerrit closes the SSH connection differently and
triggers this.

Currently the _read() function in this code interprets a 0 read as
data and continues the event loop.  This means the _listen() function
never exits.  The poll() keeps returning that there is a POLLIN event
and the _read() function keeps reading the empty FD.

Modify this to set the state to DISCONNECTED for a blank read.
Additionally improve the error message if we see invalid data (which
shouldn't happen).  Insert a short-circuit in the listen to check if
the state has switched to DISCONNECTED and exit the loop in that case.

Change-Id: I46849bcbfc3a0d409baa654867018994ce717481
This commit is contained in:
Ian Wienand 2020-11-24 11:14:03 +11:00
parent 73005984a9
commit 194ddff30a
1 changed files with 14 additions and 4 deletions

View File

@ -136,15 +136,25 @@ class GerritWatcher(threading.Thread):
def _read(self, fd):
line = fd.readline()
data = json.loads(line)
self.log.debug("Received data from Gerrit event stream: \n%s" %
pprint.pformat(data))
self.gerrit.addEvent(data)
if line:
try:
data = json.loads(line)
self.log.debug("Received data from Gerrit event stream: \n%s" %
pprint.pformat(data))
self.gerrit.addEvent(data)
except json.decoder.JSONDecodeError:
self.log.debug("Can not parse data from Gerrit event stream: \n%s" %
pprint.pformat(line))
else:
# blank read indicates EOF and the connection closed
self.state = DISCONNECTED
def _listen(self, stdout, stderr):
poll = select.poll()
poll.register(stdout.channel)
while True:
if self.state == DISCONNECTED:
return
ret = poll.poll()
for (fd, event) in ret:
if fd == stdout.channel.fileno():