Skip to content

Commit

Permalink
Logging in the 'deadlinesocket' fails if dealing with utf-8 encoded s…
Browse files Browse the repository at this point in the history
…trings.

The logging of the 'sendheader' and 'recvheader' methods needs unicode,
but the methods itself need to be fed with 'utf-8' encoded data.

See commit e20bd8b for further details.

Since thees methods itself deal with 'utf-8' encoded data, we need to
decode these data to unicode before we send them to the logging instance.

This commit provides and uses a generic function to decode strings to unicode for
python2 and python3, as well.

How to reproduce:

Start python from a PC that has mythtv frontend installed, but it is not currently
running:

When running the MythTV's python binding `BEEventMonitor`
and log events to a file, a traceback occurs:

$ python2 - --nodblog --loglevel debug --verbose all --logfile /tmp/my_logfile
>>> from MythTV import BEEventMonitor
>>> bemon = BEEventMonitor(systemevents=True)
>>> while (True):
....    continue

From another frontend, start playback of a recording that has a description
with German umlauts or French accents:

Enjoy the traceback:

Unhandled exception in thread started by
     <bound method BEEventConnection.eventloop
         of <MythTV.connections.BEEventConnection object at 0x7f6f922c1ad0>>
Traceback (most recent call last):
  File "MythTV/connections.py", line 427, in eventloop
    self.queueEvents()
  File "MythTV/connections.py", line 396, in queueEvents
    event = self.socket.recvheader(deadline=0.0)
  File "MythTV/utility/other.py", line 387, in recvheader
    'read <-- %d' % size, data)
  File "MythTV/logging.py", line 431, in __call__
    self.log(mask, level, message, detail)
  File "MythTV/logging.py", line 376, in log
    self._logwrite(mask, level, message, detail)
  File "MythTV/logging.py", line 408, in _logfile
    self._LOGFILE.write(buff.getvalue())
  File "/usr/lib/python2.7/codecs.py", line 708, in write
    return self.writer.write(data)
  File "/usr/lib/python2.7/codecs.py", line 369, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 260:
    ordinal not in range(128)
  • Loading branch information
rcrdnalor authored and Bill Meek committed Nov 15, 2019
1 parent 378cfe0 commit 455cc61
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions mythtv/bindings/python/MythTV/utility/other.py
Expand Up @@ -55,7 +55,7 @@ def run(self):
except AttributeError as e:
self.log(MythLog.GENERAL, MythLog.CRIT,
'failed at %d' % schema, 'no handler method')
raise MythDBError('Schema update failed, '
raise MythDBError('Schema update failed, '
"SchemaUpdate has no function 'up%s'" % schema)

except StopIteration:
Expand Down Expand Up @@ -383,15 +383,16 @@ def recvheader(self, flags=0, deadline=None):
"""
size = int(self.dlrecv(8, flags, deadline))
data = self.dlrecv(size, flags, deadline)
# data is utf-8 encoded, convert to unicode for logging and ignore errors
self.log(MythLog.SOCKET|MythLog.NETWORK, MythLog.DEBUG, \
'read <-- %d' % size, data)
'read <-- %d' % size, py23_str(data, True))
return data

def sendheader(self, data, flags=0):
"""Send data, prepending the length in the first 8 bytes."""
try:
self.log(MythLog.SOCKET|MythLog.NETWORK, MythLog.DEBUG, \
'write --> %d' % len(data), data)
'write --> %d' % len(data), py23_str(data, True))
data = '%-8d%s' % (len(data), data)
self.send(data, flags)
except socket.error as e:
Expand Down Expand Up @@ -572,6 +573,17 @@ def check_ipv6(n):
except socket.error:
return False

def py23_str(value, ignore_errors=False):
error_methods = ('strict', 'ignore')
error_method = error_methods[ignore_errors]
try: # Python 2
return unicode(value, errors=error_method, encoding='utf-8')
except NameError: # Python 3
try:
return str(value,errors=error_method, encoding='utf-8')
except TypeError: # Wasn't a bytes object, no need to decode
return str(value)

class QuickProperty( object ):
def __init__(self, maskedvar, default=None, handler=None):
self.varname = maskedvar
Expand Down

0 comments on commit 455cc61

Please sign in to comment.