首页 > 解决方案 > 使用 Python 处理 ctypes 函数中的无限循环

问题描述

假设我在 C 中定义了几个函数,其中一个导致无限循环。我在 Python 中使用 ctypes 模块来运行这些函数中的每一个,因此它会导致无限循环,从而导致我的 Python 脚本完全停止。

我试图在超时下运行 C 函数,但超时永远不会被触发。我该如何处理?我无法停止我的 Python 脚本,如果遇到这个无限循环函数,我的要求是打印一条错误消息,然后继续执行下一个函数。超时看起来像这样:

limit = 10
def raise_timeout(signum, frame):
    raise TimeoutError

def timeout(limit):
    signal.signal(signal.SIGALARM, raise_timeout)
    signal.alarm(limit)
    try:
        yield
    except TimeoutError:
        print('Timed out')
    finally:
        signal.signal(signal.SIGALARM, signal.SIG_IGN)


## Attempting to run function

for function in function_list:

    #Perform actions to load the shared .so library, define res/argtypes etc

    with timeout(limit):
        result = c_lib() # This is the function I run from ctypes

我看到的唯一方法是使用计时器来处理它,例如 10 秒左右。但我觉得我做错了 - 我的 Python 脚本有什么办法可以找出 ctypes 函数在 10 秒内没有响应,因此它应该以某种方式退出?

我在这里很绝望,任何有效但违背常识的hacky东西也可以。:(

任何帮助表示赞赏,谢谢。

标签: pythonloopstimeoutctypesinfinite

解决方案


如果 C 代码挂起,据我所知,Python 不会重新获得控制权。您可以尝试使用多处理池调用该函数。

演示:

import multiprocessing as mp
from multiprocessing.pool import Pool

import time

def worker(work):
    time.sleep(work)  # pretend to do some work
    return work

def call(func,work_time,timeout):
    global p
    a = p.apply_async(func,(work_time,))  # call function using pool
    try:
        result = a.get(timeout)           # wait for asynchronous result
        print(f'{result=}')
    except mp.TimeoutError:
        p.terminate()                     # kill the pool
        p.join()                          # wait for the pool processes to stop
        print('Terminated.')
        p = Pool(1)                       # restart pool

if __name__ == '__main__':
    p = Pool(1)       # global process pool (1 process)
    call(worker,1,3)
    call(worker,2,3)
    call(worker,3,3)
    call(worker,4,3)
    p.close()         # Tell all processes in pool to stop
    p.join()          # Wait for them to stop.

输出:

result=1
result=2
Terminated.
Terminated.

推荐阅读