2019-03-28 15:25:53 +00:00
|
|
|
from contextlib import suppress
|
|
|
|
from os import open as osopen
|
|
|
|
from os import write, close, O_WRONLY, O_NONBLOCK
|
2018-12-14 16:36:53 +00:00
|
|
|
from threading import Thread
|
2018-12-14 23:32:29 +00:00
|
|
|
|
|
|
|
from .terminate_process_on_failure import terminate_process_on_failure
|
2018-12-14 16:36:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
class PipeReaderThread(Thread):
|
2019-03-28 15:25:53 +00:00
|
|
|
eof = ''
|
|
|
|
stop_sequence = 'stop_reading'
|
2018-12-14 16:36:53 +00:00
|
|
|
|
2019-03-28 15:25:53 +00:00
|
|
|
def __init__(self, pipe_path, stop_event, message_handler):
|
2018-12-14 16:36:53 +00:00
|
|
|
super().__init__()
|
|
|
|
self._message_handler = message_handler
|
|
|
|
self._pipe_path = pipe_path
|
2019-03-28 15:25:53 +00:00
|
|
|
self._stop_event = stop_event
|
2018-12-14 16:36:53 +00:00
|
|
|
|
2018-12-14 23:32:29 +00:00
|
|
|
@terminate_process_on_failure
|
2018-12-14 16:36:53 +00:00
|
|
|
def run(self):
|
2019-03-28 15:25:53 +00:00
|
|
|
with open(self._pipe_path, 'r') as pipe:
|
|
|
|
while True:
|
|
|
|
message = pipe.readline().rstrip()
|
|
|
|
if message in (self.eof, self.stop_sequence):
|
|
|
|
self._stop_event.set()
|
|
|
|
break
|
|
|
|
self._message_handler(message)
|
2018-12-14 16:36:53 +00:00
|
|
|
|
|
|
|
def stop(self):
|
2019-03-28 15:25:53 +00:00
|
|
|
self.unblock()
|
2018-12-14 16:36:53 +00:00
|
|
|
self.join()
|
2019-03-28 15:25:53 +00:00
|
|
|
|
|
|
|
def unblock(self):
|
|
|
|
with suppress(OSError):
|
|
|
|
fd = osopen(self._pipe_path, O_WRONLY | O_NONBLOCK)
|
|
|
|
write(fd, f'{self.stop_sequence}\n'.encode())
|
|
|
|
close(fd)
|