0

I have a class A with a function foo() that logs information for an infinite time. I would like to execute this function for 30 sec, retrieving these logs. For the recovery of the logs, I base myself on this article, the logs being realized at the C level.

So I realized, in addition to the code of the previous article, this portion of code, allowing to stop the execution of the function after 30 seconds.

if __name__ == '__main__':
    f = io.BytesIO()
    with stdout_redirector(f):
        p = multiprocessing.Process(target=A.foo, name="myfunc")
        p.start()
        # Cleanup
        p.join(30)
        if p.is_alive():
            # Terminate foo
            p.terminate()
            p.join()
data = f.getvalue().decode('utf-8')

This works fine as is. However, I can't get this portion of the code into a fastAPI endpoint. Indeed, no matter what I try, errors around the multiprocessing appear. Either the endpoint returns nothing, or a Pickle error appears... I don't know what to do!

Here I use multiprocessing only to stop foo() after a while; maybe there is another way to avoid problems with fastAPI. Does anyone have a way to fix my problem?

EDIT #1

Based on Brandt's suggestion, the following function was done (Using windows, I can't use signals.):

@timeout_decorator.timeout(30, use_signals=False)
def run_func(func):
    f = io.BytesIO()
    with stdout_redirector(f):
       func()   
    return f.getvalue().decode('utf-8')

And the following endpoint :

@app.get('/foo')
def get_foo():
   data = run_func(A.foo)
   return {'data' : data}

but the EOFError: Ran out of input is triggered by thetimeout_decorator module.

heexos
  • 33
  • 4

2 Answers2

1

You can use the 'timeout_decorator' package:

Back in the days, it provided me the solution for a similar issue; I was/am not using FastAPI, but pretty much the same thing(AFAIU).

Basically, you just decorate the function you want to stop in case it surpasses some "T-seconds" timeout. Here is the code I used it:

Brandt
  • 5,058
  • 3
  • 28
  • 46
  • Thank you for this suggestion! I think it is based on threads though (like my program) as I think I have had this error before, I edited my post with more info. – heexos Apr 06 '22 at 14:43
0

You probably can override the returned error with the timeout_exception parameter:

@timeout_decorator.timeout(30, use_signals=False, timeout_exception=TimeoutError)

However, you may run into a different problem with the timeout_decorator. The usage of use_signals=False, in my case, caused FAST API service to shutdown after handling the timeout! This seems to be due to Fastapi thread operations as discussed here.

I ended up using the decorator without the use_signals parameter, and opening a thread to handle the method with timeout_decorator.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
Motaz
  • 1
  • 1