使用 Python 处理 ctypes 函数中的无限循环

Handling infinite loops in ctypes function with Python

假设我有几个用 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 秒内没有响应,因此它应该以某种方式退出?

我在这里很绝望,任何一种有效但违反常识的骇人听闻的东西也可以。 :(

感谢任何帮助,谢谢。

如果 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.