Gtk线程阻塞函数执行问题:指纹验证函数延迟执行排查
问题描述
我用Python编写了一段代码,尝试同时启动Gtk窗口和指纹验证线程,但fp.run_verification函数必须等Gtk窗口关闭后才会执行。相关代码如下:
主程序代码
import threading from fpysensor import fp import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk class MainWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Hello, World!") self.set_border_width(10) label = Gtk.Label() label.set_label("Hello, World!") self.add(label) def run(): win = MainWindow() win.connect("destroy", Gtk.main_quit) win.show_all() Gtk.main() threading.Thread(target=run).start() threading.Thread(target=fp.run_verification, args=("127.0.0.1", 5000)).start() while True: pass
fp模块代码
from fpysensor import __fingerprint from ctypes import c_char_p def run_enrollment(ip_addr: str, port: int): """ Run the fingerprint enrollment process """ __ip_cp = c_char_p(ip_addr.encode('utf-8')) __fingerprint.py_run_enrollment(__ip_cp, port) def run_verification(ip_addr: str, port: int): """ Run verification against the fingerprints stored """ __ip_cp = c_char_p(ip_addr.encode('utf-8')) __fingerprint.py_run_verification(__ip_cp, port)
共享库加载代码
__fingerprint = ctypes.CDLL(f"{__wd}/lib.so")
我通过fp模块调用lib.so共享库,想确认:是Gtk阻塞了所有线程,还是我的C库存在问题?
问题原因及解决办法
核心问题:主线程的死循环
代码末尾的while True: pass会让主线程持续占用CPU,结合CPython的GIL(全局解释器锁)机制,这个死循环会一直持有GIL,导致其他子线程无法获得执行权限——包括指纹验证线程。只有当Gtk窗口关闭、Gtk.main()退出后,主线程的死循环才会让GIL调度出现变化,但这并非正确的执行逻辑。Gtk的线程规范
Gtk并非线程安全,所有UI相关操作必须在主线程执行。你当前把Gtk窗口放到子线程运行的做法不符合规范,后续可能引发未知问题。正确的模式是将Gtk事件循环放在主线程,把指纹验证这类耗时操作放到子线程。修复后的代码示例
移除主线程的死循环,将Gtk逻辑移回主线程:import threading from fpysensor import fp import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk class MainWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Hello, World!") self.set_border_width(10) label = Gtk.Label() label.set_label("Hello, World!") self.add(label) # 指纹验证放在子线程运行,设置daemon=True让线程随主线程退出 threading.Thread(target=fp.run_verification, args=("127.0.0.1", 5000), daemon=True).start() # Gtk事件循环在主线程执行 win = MainWindow() win.connect("destroy", Gtk.main_quit) win.show_all() Gtk.main()C库排查方向
如果按上述修改后问题仍存在,再排查C库:检查lib.so中的py_run_verification函数是否存在阻塞逻辑,或者是否在内部未正确释放GIL。但从当前代码看,主线程的死循环是最直接的诱因。
内容的提问来源于stack exchange,提问作者Parker
相关产品推荐
相关产品推荐

