守护进程内的Python多处理池

时间:2011-06-29 06:24:02

标签: python multithreading threadpool multiprocessing pool

我为这个问题提出了一个问题,并没有得到足够彻底的答案来解决这个问题(很可能是由于在解释我的问题时缺乏严谨性,这是我试图纠正的问题):{{3} }

我正在尝试实现一个python守护程序,它使用一个worker池来使用Popen执行命令。我从Zombie process in python multiprocessing daemon

借用了基本守护进程

我只更改了initdaemonize(或同等start)和stop方法。以下是init方法的更改:

def __init__(self, pidfile):
#, stdin='/dev/null', stdout='STDOUT', stderr='STDOUT'):
    #self.stdin = stdin
    #self.stdout = stdout
    #self.stderr = stderr
    self.pidfile = pidfile
    self.pool = Pool(processes=4)

我没有设置stdin,stdout和stderr,因此我可以使用print语句调试代码。此外,我已经尝试将此池移动到几个地方,但这是唯一不会产生异常的地方。

以下是daemonize方法的更改:

def daemonize(self):
    ...

    # redirect standard file descriptors
    #sys.stdout.flush()
    #sys.stderr.flush()
    #si = open(self.stdin, 'r')
    #so = open(self.stdout, 'a+')
    #se = open(self.stderr, 'a+', 0)
    #os.dup2(si.fileno(), sys.stdin.fileno())
    #os.dup2(so.fileno(), sys.stdout.fileno())
    #os.dup2(se.fileno(), sys.stderr.fileno())

    print self.pool

    ...

同样的事情,我没有重定向io以便我可以调试。这里使用打印,以便我可以检查池位置。

stop方法更改:

def stop(self):
    ...

    # Try killing the daemon process
    try:
        print self.pool
        print "closing pool"
        self.pool.close()
        print "joining pool"
        self.pool.join()
        print "set pool to None"
        self.pool = None
        while 1:
            print "kill process"
            os.kill(pid, SIGTERM)

    ...

这里的想法是,我不仅需要杀死进程,还需要清理池。 self.pool = None只是随机尝试解决无法解决的问题。起初我认为这是僵尸儿童的一个问题,当我在self.pool.close()的while循环中使用self.pool.join()os.kill(pid, SIGTERM)时发生了这个问题。这是在我决定通过print self.pool开始查看游泳池位置之前。执行此操作后,我相信守护程序启动时和停止时池不同。这是一些输出:

me@pc:~/pyCode/jobQueue$ sudo ./jobQueue.py start
<multiprocessing.pool.Pool object at 0x1c543d0>
me@pc:~/pyCode/jobQueue$ sudo ./jobQueue.py stop
<multiprocessing.pool.Pool object at 0x1fb7450>
closing pool
joining pool
set pool to None
kill process
kill process
... [ stuck in infinite loop]

对象的不同位置告诉我他们不是同一个游泳池,其中一个可能是僵尸?

CTRL+C之后,这是我从ps aux|grep jobQueue得到的:

root     21161  0.0  0.0  50384  5220 ?        Ss   22:59   0:00 /usr/bin/python ./jobQueue.py start
root     21162  0.0  0.0      0     0 ?        Z    22:59   0:00 [jobQueue.py] <defunct>
me       21320  0.0  0.0   7624   940 pts/0    S+   23:00   0:00 grep --color=auto jobQueue

我尝试将self.pool = Pool(processes=4)移到许多不同的地方。如果它被移动到start()' or daemonize()methods,,则print self.pool`会抛出一个异常,说它是NoneType。此外,该位置似乎会改变弹出的僵尸进程数量。

目前,我还没有添加通过worker运行任何东西的功能。我的问题似乎与正确设置工作池完全相关。我将不胜感激任何导致解决此问题的信息或有关创建使用工作池来使用Popen执行一系列命令的守护程序服务的建议。由于我没有那么远,我不知道我面临的挑战是什么。我想我可能只需要编写自己的游泳池,但如果有一个很好的技巧可以让游泳池在这里工作,那就太棒了。

1 个答案:

答案 0 :(得分:1)

解决方案是将self.pool = Pool(process=4)作为daemonize方法的最后一行。否则,游戏池最终会在某处丢失(可能在fork s)。然后可以在run方法内访问该池,该方法由您希望守护的应用程序重载。但是,无法在stop方法中访问池,这样做会导致NoneType异常。我相信有一个更优雅的解决方案,但这是有效的,这就是我现在所拥有的。如果我希望stop在游戏池仍在运行时失败,我将不得不向run添加其他功能以及某种形式的消息,但我目前并不关心这一点。