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
所以我有一个队列:
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