Python: 进程挂起 futex(0x2a5fcc0, FUTEX_WAIT_PRIVATE, 0, NULL in multithreading

Python: Process hangs with futex(0x2a5fcc0, FUTEX_WAIT_PRIVATE, 0, NULL in multithreading

所以我有一个队列:

q = Queue.Queue()

我正在里面放一些东西。

items = ["First", "Second"]
for val in items:
    q.put(val)

我生成了 15 个线程。

for i in range(15):
   tname = 't-%s' % i
   t = my_thread(some_func, q, tname)
   t.start()

q.join()

my_thread class 如下所示:

class my_thread(threading.Thread):
    def __init__(self, some_func, q_, name=''):
       threading.Thread.__init__(self)
       self.func = some_func
       self.process_q = q_
       self.name = name
       self.prefix = name


    def run(self):
       stime = time.time()
       logging.info('%s thread staring at : %s' % (threading.currentThread().getname(), time.ctime(stime)))
       while True:
           if self.process_q.empty():
               break
           queue_item = self.process_q.get()
           self.name = self.prefix + '-' + queue_item
           try:
               #run the function
           except Exception as e:
               logging.error('Caught some error')
           finally:
               self.process_q.task_done()


       endTime = time.time()
       logging.info('%s thread finished at: %s' % (threading.currentThread().getName(), time.ctime(endTime)))

如果我查看日志,我看到两个或多个线程同时访问队列,并且当队列为空时 while 循环不会中断。

假设 t-0 线程已从队列中取出 "first" 项。 但是 t-2 线程可能会在 t-1 线程可以获取它之前获取 "second" 项,从而使队列为空...但是当 t-1 执行 self.process_q.empty() 检查时,队列不是空的。所以 t-1 线程永远不会 exits/finishes 并且被挂起。

如果我对进程 ID 进行跟踪,我会得到以下信息:

Process 13307 attached
futex(0x2a5fcc0, FUTEX_WAIT_PRIVATE, 0, NULL

我该如何解决???

您的线程随机挂在阻塞的 self.process_q.get() 函数中。 -> 竞争条件

此时线程已经启动,队列不为空。 代码部分...

...
if self.process_q.empty():
    break
queue_item = self.process_q.get()
...

未在所有线程上同步。因此可能有超过 2 个线程(队列大小 = 2)通过 if 条件。两个线程正在从 self.process_q.get() 函数获取结果,而其他线程正在阻塞并等待队列中的结果。

在所有非守护线程完成之前,python 程序无法退出。所以它永远挂起。

考虑将线程设置为守护进程模式:

for i in range(15):
    tname = 't-%s' % i
    t = my_thread(some_func, q, tname)
    t.setDaemon(True)
    t.start()

来自 https://docs.python.org/2/library/threading.html#threading.Thread.daemon :

daemon

A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False.

The entire Python program exits when no alive non-daemon threads are left.

通过将daemon-mode设置为true,程序在队列为空后退出(q.join()) .

我遇到了同样的问题并确定在 RHEL7 上有一个“python /usr/bin/goferd”进程消耗 100% CPU机.

[root@RHELLINUXPROD~]# ps辅助 | grep -i 1268 根 1268 90.4 0.0 1030428 25304 ? SSL Jun 04 111901:11 python /usr/bin/goferd --foreground

问题识别: 此“/usr/bin/goferd”过程将与客户端计算机上的 RedHat 卫星订阅相关。

这是 RedHat 卫星订阅代理的错误 "katello-ca-consumer-latest.noarch.rpm"

解法:

临时解决方案:

找出你的 RHEL7 机器上安装的 katello 代理。

[root@RHELLINUXPROD~]# katello-ca-consumer-rhsat-i01.0-1.noarch katello-agent-1.5.3-7.el7sat.noarch

清理并注销客户端 RHEL7 机器上的 Redhat 订阅

*# 订阅管理器清理

订阅管理器注销*

从 RHEL7 客户端移除已安装的 katello 代理

[root@RHELLINUXPROD~]# rpm -e katello-ca-consumer-rhsat-i01.0-1.noarch [root@RHELLINUXPROD~]# rpm -e katello-agent-1.5.3-7.el7sat.noarch

现在您可以看到使用 "ps -ef | grep -i goferd " 命令输出 python 进程已停止并且服务器 CPU 利用率变得正常。

再次重新安装katello aganet并将服务器订阅到redhat satellite。

永久解决方案:

您必须将您的卫星升级到最新版本,然后才能永久解决此问题。

感谢和问候 Namasivayam