2011-10-29 03:11:30 +00:00
|
|
|
"""
|
|
|
|
Defines the Fifo class
|
2014-04-22 17:57:25 +00:00
|
|
|
|
|
|
|
This fifo allows simple communication between a remote poezio
|
|
|
|
and a local computer, with ssh+cat.
|
2011-10-29 03:11:30 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
import logging
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
import os
|
|
|
|
import threading
|
|
|
|
|
|
|
|
class OpenTrick(threading.Thread):
|
|
|
|
"""
|
|
|
|
A threaded trick to make the open for writing succeed.
|
|
|
|
A fifo cannot be opened for writing if it has not been
|
|
|
|
yet opened by the other hand for reading.
|
2014-04-22 17:57:25 +00:00
|
|
|
So, we just open the fifo for reading and we do not close
|
|
|
|
it afterwards, because if the other reader disconnects,
|
|
|
|
we will receive a SIGPIPE. And we do not want that.
|
|
|
|
|
|
|
|
(we never read anything from it, obviously)
|
2011-10-29 03:11:30 +00:00
|
|
|
"""
|
|
|
|
def __init__(self, path):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.path = path
|
2014-04-19 04:36:10 +00:00
|
|
|
self.fd = None
|
2011-10-29 03:11:30 +00:00
|
|
|
|
|
|
|
def run(self):
|
2014-04-19 04:36:10 +00:00
|
|
|
self.fd = open(self.path, 'r', encoding='utf-8')
|
2011-10-29 03:11:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Fifo(object):
|
|
|
|
"""
|
|
|
|
Just a simple file handler, writing and reading in a fifo.
|
|
|
|
Mode is either 'r' or 'w', just like the mode for the open()
|
|
|
|
function.
|
|
|
|
"""
|
|
|
|
def __init__(self, path, mode):
|
|
|
|
self.trick = None
|
|
|
|
if not os.path.exists(path):
|
|
|
|
os.mkfifo(path)
|
|
|
|
if mode == 'w':
|
|
|
|
self.trick = OpenTrick(path)
|
|
|
|
# that thread will wait until we open it for writing
|
|
|
|
self.trick.start()
|
2012-09-13 07:48:35 +00:00
|
|
|
self.fd = open(path, mode, encoding='utf-8')
|
2011-10-29 03:11:30 +00:00
|
|
|
|
|
|
|
def write(self, data):
|
|
|
|
"""
|
|
|
|
Try to write on the fifo. If that fails, this means
|
|
|
|
that nothing has that fifo opened, so the writing is useless,
|
|
|
|
so we just return (and display an error telling that, somewhere).
|
|
|
|
"""
|
|
|
|
self.fd.write(data)
|
|
|
|
self.fd.flush()
|
|
|
|
|
|
|
|
def readline(self):
|
2014-04-22 17:57:25 +00:00
|
|
|
"Read a line from the fifo"
|
2011-10-29 03:11:30 +00:00
|
|
|
return self.fd.readline()
|
|
|
|
|
|
|
|
def __del__(self):
|
2014-04-22 17:57:25 +00:00
|
|
|
"Close opened fds"
|
2011-10-29 03:11:30 +00:00
|
|
|
try:
|
|
|
|
self.fd.close()
|
2014-04-22 17:57:25 +00:00
|
|
|
if self.trick:
|
|
|
|
self.trick.fd.close()
|
2011-10-29 03:11:30 +00:00
|
|
|
except:
|
2014-04-22 17:57:25 +00:00
|
|
|
log.error('Unable to close descriptors for the fifo',
|
|
|
|
exc_info=True)
|