Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from sm_typing import Any, Callable, Dict, Optional, override 

2 

3import os 

4import socket 

5import inspect 

6import time 

7 

8SOCKDIR = "/run/fairlock" 

9START_SERVICE_TIMEOUT_SECS = 2 

10 

11class SingletonWithArgs(type): 

12 _instances: Dict[Any, Any] = {} 

13 _init: Dict[type, Optional[Callable[..., None]]] = {} 

14 

15 def __init__(cls, name, bases, dct): 

16 cls._init[cls] = dct.get('__init__', None) 

17 

18 @override 

19 def __call__(cls, *args, **kwargs) -> Any: 

20 init = cls._init[cls] 

21 if init is not None: 21 ↛ 25line 21 didn't jump to line 25, because the condition on line 21 was never false

22 key: Any = (cls, frozenset( 

23 inspect.getcallargs(init, None, *args, **kwargs).items())) 

24 else: 

25 key = cls 

26 

27 if key not in cls._instances: 

28 cls._instances[key] = super(SingletonWithArgs, cls).__call__(*args, **kwargs) 

29 return cls._instances[key] 

30 

31class FairlockDeadlock(Exception): 

32 pass 

33 

34class FairlockServiceTimeout(Exception): 

35 pass 

36 

37class Fairlock(metaclass=SingletonWithArgs): 

38 def __init__(self, name): 

39 self.name = name 

40 self.sockname = os.path.join(SOCKDIR, name) 

41 self.connected = False 

42 

43 def _ensure_service(self): 

44 service=f"fairlock@{self.name}.service" 

45 os.system(f"/usr/bin/systemctl start {service}") 

46 timeout = time.time() + START_SERVICE_TIMEOUT_SECS 

47 time.sleep(0.1) 

48 while os.system(f"/usr/bin/systemctl --quiet is-active {service}") != 0: 

49 time.sleep(0.1) 

50 if time.time() > timeout: 

51 raise FairlockServiceTimeout(f"Timed out starting service {service}") 

52 

53 def __enter__(self): 

54 if self.connected: 

55 raise FairlockDeadlock(f"Deadlock on Fairlock resource '{self.name}'") 

56 

57 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 

58 try: 

59 self.sock.connect(self.sockname) 

60 except (FileNotFoundError, ConnectionRefusedError): 

61 self._ensure_service() 

62 self.sock.connect(self.sockname) 

63 

64 self.sock.send(f'{os.getpid()} - {time.monotonic()}'.encode()) 

65 self.connected = True 

66 return self 

67 

68 def __exit__(self, type, value, traceback): 

69 self.sock.close() 

70 self.connected = False 

71 return False 

72