mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
2fc11ab055
Add the possibility of passing a list of FIFOs to `revng daemon`. These can be used to notify an external program when a non-reproducible change (binary, context) has occurred.
70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
#
|
|
# This file is distributed under the MIT License. See LICENSE.md for details.
|
|
#
|
|
|
|
import logging
|
|
import os
|
|
from abc import ABC, abstractmethod
|
|
from pathlib import Path
|
|
from tempfile import mkdtemp
|
|
|
|
from revng.api.listenable_manager import EventType, ListenableManager
|
|
from revng.api.manager import Manager
|
|
|
|
|
|
class BaseListener(ABC):
|
|
def __init__(self, fifo_path: Path):
|
|
self.fifo = open(fifo_path, "w") # noqa: SIM115
|
|
|
|
@abstractmethod
|
|
def __call__(self, manager: Manager, type_: EventType):
|
|
pass
|
|
|
|
def write_fifo(self, content: str):
|
|
try:
|
|
self.fifo.write(content)
|
|
self.fifo.flush()
|
|
except (BrokenPipeError, FileNotFoundError, PermissionError, TimeoutError) as e:
|
|
logging.warn(
|
|
f"Encountered error when writing to notification pipe: {repr(e)}",
|
|
)
|
|
|
|
def __del__(self):
|
|
self.fifo.close()
|
|
|
|
|
|
class BeginListener(BaseListener):
|
|
def __call__(self, manager: Manager, type_: EventType):
|
|
assert type_ == EventType.BEGIN
|
|
begin_step = manager.get_step("begin")
|
|
assert begin_step is not None
|
|
|
|
tmpdir = mkdtemp()
|
|
begin_step.save(tmpdir)
|
|
self.write_fifo(f"PUSH begin {tmpdir}\n")
|
|
|
|
|
|
class ContextListener(BaseListener):
|
|
def __call__(self, manager: Manager, type_: EventType):
|
|
assert type_ == EventType.CONTEXT
|
|
tmpdir = mkdtemp()
|
|
manager.save_context(tmpdir)
|
|
self.write_fifo(f"PUSH context {tmpdir}\n")
|
|
|
|
|
|
def make_manager(workdir: Path):
|
|
if "REVNG_NOTIFY_FIFOS" not in os.environ:
|
|
return Manager(str(workdir.resolve()))
|
|
|
|
manager = ListenableManager(str(workdir.resolve()))
|
|
for fifo_definition in os.environ["REVNG_NOTIFY_FIFOS"].split(","):
|
|
fifo_path, string_type = fifo_definition.split(":", 1)
|
|
if string_type == "begin":
|
|
manager.add_event_listener(EventType.BEGIN, BeginListener(Path(fifo_path)))
|
|
elif string_type == "context":
|
|
manager.add_event_listener(EventType.CONTEXT, ContextListener(Path(fifo_path)))
|
|
else:
|
|
logging.warn(f"Unknown event type specified for fifo: {string_type}")
|
|
|
|
return manager
|