1
1
import os
2
+ from concurrent import futures
2
3
from io import SEEK_SET , UnsupportedOperation
3
4
from pathlib import Path
4
5
from stat import S_IRGRP , S_IROTH , S_IRUSR
6
+ from typing import Any , Callable
5
7
6
8
from dissect .util .stream import AlignedStream
7
9
14
16
HAS_FCNTL = False
15
17
16
18
19
+ def timeout (func : Callable , * , timelimit : int ) -> Callable :
20
+ """Timeout a function if it takes too long to complete.
21
+
22
+ Args:
23
+ func: a function to wrap.
24
+ timelimit: The time in seconds that an operation is allowed to run.
25
+
26
+ Raises:
27
+ TimeoutError: If its time exceeds the timelimit
28
+ """
29
+
30
+ def wrapper (* args : Any , ** kwargs : Any ) -> Any :
31
+ with futures .ThreadPoolExecutor (max_workers = 1 ) as executor :
32
+ future = executor .submit (func , * args , ** kwargs )
33
+
34
+ try :
35
+ result = future .result (timelimit )
36
+ except futures .TimeoutError :
37
+ raise TimeoutError
38
+ finally :
39
+ # Make sure the thread stops right away.
40
+ executor ._threads .clear ()
41
+ futures .thread ._threads_queues .clear ()
42
+
43
+ return result
44
+
45
+ return wrapper
46
+
47
+
17
48
class VolatileStream (AlignedStream ):
18
49
"""Streaming class to handle various procfs and sysfs edge-cases. Backed by `AlignedStream`.
19
50
@@ -41,6 +72,8 @@ def __init__(
41
72
st_mode = os .fstat (self .fd ).st_mode
42
73
write_only = (st_mode & (S_IRUSR | S_IRGRP | S_IROTH )) == 0 # novermin
43
74
75
+ self ._os_read = timeout (os .read , timelimit = 5 )
76
+
44
77
super ().__init__ (0 if write_only else size )
45
78
46
79
def seek (self , pos : int , whence : int = SEEK_SET ) -> int :
@@ -53,8 +86,8 @@ def _read(self, offset: int, length: int) -> bytes:
53
86
result = []
54
87
while length :
55
88
try :
56
- buf = os . read (self .fd , min (length , self .size - offset ))
57
- except BlockingIOError :
89
+ buf = self . _os_read (self .fd , min (length , self .size - offset ))
90
+ except ( BlockingIOError , TimeoutError ) :
58
91
break
59
92
60
93
if not buf :
0 commit comments