Thread._wait_for_tstate_lock()永远不会返回

16

我发现我的程序有时会在按下Ctrl+C时陷入死锁状态。我尝试捕获键盘中断并优雅地停止所有运行的线程,但我还没有达到这个目标。

我正在使用concurrent.futures.ThreadPoolExecutor。为了找到死锁的位置,我正在使用ActiveState提供的这个技巧

以下是完整的堆栈跟踪:

# ThreadID: 4856
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\threading.py", line 884, in _bootstrap
  self._bootstrap_inner()
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\threading.py", line 916, in _bootstrap_inner
  self.run()
File: "C:\Users\niklas\repos\nodepy\craftr\lib\utils\tracer.py", line 66, in run
  self.stacktraces()
File: "C:\Users\niklas\repos\nodepy\craftr\lib\utils\tracer.py", line 80, in stacktraces
  fout.write(stacktraces())
File: "C:\Users\niklas\repos\nodepy\craftr\lib\utils\tracer.py", line 28, in stacktraces
  for filename, lineno, name, line in traceback.extract_stack(stack):

# ThreadID: 6068
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\runpy.py", line 193, in _run_module_as_main
  "__main__", mod_spec)
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\runpy.py", line 85, in _run_code
  exec(code, run_globals)
File: "C:\Users\niklas\repos\nodepy\craftr\.nodepy_modules\.bin\craftr.exe\__main__.py", line 9, in <module>
  sys.exit(nodepy.main.main())
File: "c:\users\niklas\repos\nodepy\nodepy\nodepy\main.py", line 103, in main
  ctx.load_module(ctx.main_module, do_init=False)
File: "c:\users\niklas\repos\nodepy\nodepy\nodepy\context.py", line 253, in load_module
  module.load()
File: "c:\users\niklas\repos\nodepy\nodepy\nodepy\loader.py", line 43, in load
  exec(code, vars(self.namespace))
File: "C:\Users\niklas\repos\nodepy\craftr\lib\main.py", line 110, in <module>
  sys.exit(main())
File: "C:\Users\niklas\repos\nodepy\craftr\lib\main.py", line 106, in main
  return backend.build_main(backend_args, session, module)
File: "C:\Users\niklas\repos\nodepy\craftr\lib\build_backends\default.py", line 194, in build_main
  executor.run(actions)
File: "C:\Users\niklas\repos\nodepy\craftr\lib\build_backends\default.py", line 171, in run
  self.wait()
File: "C:\Users\niklas\repos\nodepy\craftr\lib\build_backends\default.py", line 137, in wait
  self.pool.shutdown(wait=True)
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\concurrent\futures\thread.py", line 144, in shutdown
  t.join()
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\threading.py", line 1056, in join
  self._wait_for_tstate_lock()
File: "c:\users\niklas\appdata\local\programs\python\python36\lib\threading.py", line 1072, in _wait_for_tstate_lock
  elif lock.acquire(block, timeout):

我无法从这个回溯中理解。看起来Thread._wait_for_tstate_lock()永远不会返回(我检查了多次,它总是停留在那一行)。除了主线程(6068)和跟踪器线程(4856)之外没有其他线程在运行。

我不太理解threading.Thread的实现细节。什么原因会导致Thread._tstate_lock.acquire()无限期地阻塞?


更新 2017/11/07 -- 01:45am CEWT

当多次调用pool.shutdown()时,似乎会发生这种情况...

2个回答

9
我不完全确定这是你在Windows上看到这个问题的原因,但我在Linux下使用Python 3.6遇到了一个类似的场景。 我在 concurrent.futures.ThreadPoolExecutor 上使用了 .shutdown(),程序似乎会卡住。有时需要30-60秒才能最终退出。Ctrl-C 始终导致回溯,显示程序正处于 _wait_for_tstate_lock() 中。请注意:在Python 3中,第二个 Ctrl-C 实际上会退出。我的问题出现在被提交的函数中使用了循环中的 time.sleep()。查看当前github上的nodepy代码中的HtmlFileTracer实现,我看到与我所做的类似的情况(连续循环并睡眠一段时间,除非设置了某种标志)。

0

如果可以(即如果你的逻辑允许),请设置 daemon=True

  • 继承ThreadPoolExecutor
  • 重写 _adjust_thread_count 方法,在创建线程时设置 daemon=True

这将确保程序在某些线程挂起时仍能完成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接