-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsandbox_instance.py
167 lines (147 loc) · 5.26 KB
/
sandbox_instance.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import asyncio
import aiofiles
import os
from .utils import rmdir, unlink
from .utils import log
class SandboxInstance:
def __init__(
self, pid, cgroup, stdinFIFO, stdoutFIFO, stderrFIFO, stdinFIFOName, stdoutFIFOName, stderrFIFOName, endedCallback=None,
):
self.pid = pid
self.cgroup = cgroup
self.stdinFIFO = stdinFIFO
self.stdoutFIFO = stdoutFIFO
self.stderrFIFO = stderrFIFO
self.stdinFIFOName = stdinFIFOName
self.stdoutFIFOName = stdoutFIFOName
self.stderrFIFOName = stderrFIFOName
self.initialized = False
self.initialized = False
self.initializedFuture = asyncio.Future()
self.isEnded = False
self.endedCallback = endedCallback
self.endedFuture = asyncio.Future()
self.stdoutContent = None
self.stderrContent = None
self.isCleaned = False
def __del__(self):
if not self.isCleaned:
asyncio.create_task(self.cleanUp())
async def openFIFO(self):
self.stdinFIFO, self.stdoutFIFO, self.stderrFIFO = await asyncio.gather(
self.stdinFIFO, self.stdoutFIFO, self.stderrFIFO
)
async def initialize(self):
await asyncio.gather(self.openFIFO())
self.initialized = True
self.initializedFuture.set_result(None)
async def cleanUp(self):
# log(f"Clean up sandbox instance [PID: {self.pid}, CGROUP: {self.cgroup}]")
self.isCleaned = True
await asyncio.gather(
self.stdinFIFO.close(), self.stdoutFIFO.close(), self.stderrFIFO.close()
)
os.unlink(self.stdinFIFOName)
os.unlink(self.stdoutFIFOName)
os.unlink(self.stderrFIFOName)
async def _end(self, result):
log(f"Sandbox instance [PID: {self.pid}, CGROUP: {self.cgroup}] ended")
self.isEnded = True
self.endedFuture.set_result(result)
if self.endedCallback:
asyncio.create_task(self.endedCallback(result))
def waitForStop(self):
return self.endedFuture
async def getStdoutContent(self):
if not self.stdoutContent:
self.stdoutContent = await self.stdoutFIFO.read()
return self.stdoutContent
async def getStderrContent(self):
if not self.stderrContent:
self.stderrContent = await self.stderrFIFO.read()
return self.stderrContent
async def forceStop(self):
try:
await self.thaw()
except:
pass
try:
os.kill(self.pid, 9)
except:
log(f"{self.pid} not found")
finally:
log(f"force {self.pid} stop done")
return await self.endedFuture
async def freeze(self):
if self.isEnded:
return
try:
async with aiofiles.open(
f"/sys/fs/cgroup/freezer/{self.cgroup}/freezer.state", mode="w"
) as f:
await f.write("FROZEN")
except OSError:
pass
async def thaw(self):
if self.isEnded:
return
try:
async with aiofiles.open(
f"/sys/fs/cgroup/freezer/{self.cgroup}/freezer.state", mode="w"
) as f:
await f.write("THAWED")
except OSError:
pass
async def readCgroupProperty(self, controllerName, propertyName):
async with aiofiles.open(
f"/sys/fs/cgroup/{controllerName}/{self.cgroup}/{propertyName}", mode="r"
) as f:
return await f.read()
async def readCgroupProperty2(self, controllerName, propertyName, subProperty):
async with aiofiles.open(
f"/sys/fs/cgroup/{controllerName}/{self.cgroup}/{propertyName}", mode="r"
) as f:
s = await f.read()
return dict(line.split() for line in s.split("\n") if line)
async def getMemUsage(self):
try:
memUsageWithCache = int(
await self.readCgroupProperty(
"memory", "memory.memsw.max_usage_in_bytes"
)
)
cacheUsage = int(
(await self.readCgroupProperty2("memory", "memory.stat", "cache"))[
"cache"
]
)
return memUsageWithCache - cacheUsage
except OSError:
return (await self.endedFuture)["memory"]
async def getCpuTimeUsage(self):
try:
actualCpuTime = int(
await self.readCgroupProperty("cpuacct", "cpuacct.usage")
)
return actualCpuTime
except OSError:
await self.endedFuture
return self.endedFuture["time"]
async def getUserCpuTimeUsage(self):
try:
actualCpuTime = int(
await self.readCgroupProperty("cpuacct", "cpuacct.usage_user")
)
return actualCpuTime
except OSError:
await self.endedFuture
return self.endedFuture["user_time"]
async def getSysCpuTimeUsage(self):
try:
actualCpuTime = int(
await self.readCgroupProperty("cpuacct", "cpuacct.usage_sys")
)
return actualCpuTime
except OSError:
await self.endedFuture
return self.endedFuture["sys_time"]