使用 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.
假设我有几个用 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.