I am interested in sandboxing a user-supplied function. This function must run asynchronously with an HTTP server. The first requirement would be to force exit the trial function if it takes too long so the server can get back to handling requests. At this point I'm not worried about malicious code, just catching programmer errors and reporting them nicely. I've implemented a "timeout" using a timer interrupt callback that raises an Exception and finally calls `machine.reset()` here is an example:
Code: Select all
import machine, time
from machine import Timer
TIMEOUT_MS = 5000 #soft-reset will happen around 5 sec
def timeout_callback(t):
try:
raise Exception("Timeout!")
finally:
machine.reset() #FIXME, gentler way to break out?
def trial_function():
cnt = 0
while True:
print("%d..." % cnt)
time.sleep(1.0)
cnt += 1
try:
timer = Timer(0)
timer.init(period=TIMEOUT_MS, mode=Timer.ONE_SHOT, callback=timeout_callback)
trial_function()
timer.deinit()
except Exception as exc:
print("Caught exc: %s" % exc)
My question is to ask if any - less heavy-handed ways - of aborting this trial function are possible? Preferably, a timeout exception might be generated in the scope where the function runs, in order to be handled along with other exceptions. However, I've read in the
Writing interrupt handlers guide that exceptions generated in ISRs are
not forwarded to the main program; indeed the Exception's message is printed when the callback fires, but without `machine.reset()` the trial function keeps on counting. Clearly, there exist serval implementations that can timeout arbitrary functions in CPython environments, such as this
ActiveState recipe using the multiprocessing library; but I doubt this approach could work directly in micropython (no processes to kill?). The EPS8266 and possibly the ESP32 are the ports that I am considering using for my project. I would even be willing to consider using a C-coded extension which could interact directly with the interpreter. Thanks in advance for your help,
- Craig