Python 退出守护进程时出现问题
我正在编写一个守护程序,它会生成其他几个子进程。在我运行Python 退出守护进程时出现问题,python,daemon,multiprocessing,Python,Daemon,Multiprocessing,我正在编写一个守护程序,它会生成其他几个子进程。在我运行stop脚本之后,当主进程打算退出时,它会继续运行,这让我很困惑 import daemon, signal from multiprocessing import Process, cpu_count, JoinableQueue from http import httpserv from worker import work class Manager: """ This manager starts the htt
stop
脚本之后,当主进程打算退出时,它会继续运行,这让我很困惑
import daemon, signal
from multiprocessing import Process, cpu_count, JoinableQueue
from http import httpserv
from worker import work
class Manager:
"""
This manager starts the http server processes and worker
processes, creates the input/output queues that keep the processes
work together nicely.
"""
def __init__(self):
self.NUMBER_OF_PROCESSES = cpu_count()
def start(self):
self.i_queue = JoinableQueue()
self.o_queue = JoinableQueue()
# Create worker processes
self.workers = [Process(target=work,
args=(self.i_queue, self.o_queue))
for i in range(self.NUMBER_OF_PROCESSES)]
for w in self.workers:
w.daemon = True
w.start()
# Create the http server process
self.http = Process(target=httpserv, args=(self.i_queue, self.o_queue))
self.http.daemon = True
self.http.start()
# Keep the current process from returning
self.running = True
while self.running:
time.sleep(1)
def stop(self):
print "quiting ..."
# Stop accepting new requests from users
os.kill(self.http.pid, signal.SIGINT)
# Waiting for all requests in output queue to be delivered
self.o_queue.join()
# Put sentinel None to input queue to signal worker processes
# to terminate
self.i_queue.put(None)
for w in self.workers:
w.join()
self.i_queue.join()
# Let main process return
self.running = False
import daemon
manager = Manager()
context = daemon.DaemonContext()
context.signal_map = {
signal.SIGHUP: lambda signum, frame: manager.stop(),
}
context.open()
manager.start()
stop
脚本只是一行的os.kill(pid,signal.SIGHUP)
,但是在那之后,子进程(工作进程和http服务器进程)很好地结束了,但是主进程只是停留在那里,我不知道是什么阻止了它返回。我尝试了另一种方法,这似乎有效(注意,我去掉了代码的守护进程部分,因为我没有安装该模块)
一个警告是signal.pause()将取消任何信号的暂停,因此您可能需要相应地更改代码
编辑:
以下内容对我来说很好:
import daemon
import signal
import time
class Manager:
"""
This manager starts the http server processes and worker
processes, creates the input/output queues that keep the processes
work together nicely.
"""
def __init__(self):
self.NUMBER_OF_PROCESSES = 5
def start(self):
# all your code minus the loop
print "waiting to die"
self.running = 1
while self.running:
time.sleep(1)
print "quit"
def stop(self):
print "quitting ..."
# all your code minus self.running
self.running = 0
manager = Manager()
context = daemon.DaemonContext()
context.signal_map = {signal.SIGHUP : lambda signum, frame: manager.stop()}
context.open()
manager.start()
您使用的是哪一版本的python?您创建了http服务器进程,但没有加入它。如果您不是执行一个
os.kill()
来停止http服务器进程,而是向它发送一个停止处理哨兵(None
,就像发送给工作人员一样),然后执行一个self.http.join()
,会发生什么情况
更新:您还需要为每个工作人员向输入队列发送一次None
哨兵。您可以尝试:
for w in self.workers:
self.i_queue.put(None)
for w in self.workers:
w.join()
注意:您需要两个循环的原因是,如果您将None
放入执行join()
的同一个循环中的队列,那么None
可能会被w
以外的工作人员拾取,因此打开w
将导致调用方阻塞
您没有为worker或http服务器显示代码,因此我假设这些在调用task_done等方面表现良好,并且每个worker在看到None
时都会退出,而不会从输入队列中删除更多内容
另外,请注意,至少有
JoinableQueue.task_done()
,它可能会咬到您。您是否看到“退出…”打印出来?我按原样尝试了你的代码,但没有守护程序模块,它对我有效。你能给我一个链接到你的守护程序模块版本吗?谷歌搜索揭示了一些选择。很抱歉我反应太晚,对于我使用@grieve的守护程序模块,我从来没有看到“退出…”,因为stdout和stderr在被守护时被重定向到一个日志文件,但即使在重定向的文件中,我也没有看到它。@Joshua:你是对的,我早期的回答不值得赏金,我已经删除了它。但是,我认为否决是不公平的。我不介意失去代表,我可以接受;我只是认为否决是不对的在回答这个问题之前,答案是正确的。给我留下评论就足够了(无论如何,这就是我来这里的原因).既然如此明显地没有告诉你,如果悬赏是放在你回答的问题上的,我希望你不是在暗示我故意等待悬赏在我站起来之前落地。我自己不会手动处理信号,而是在代码中的while true循环确实是self.http.join()中处理守护进程模块,但有一个进程没有退出,然后我将其替换为while true循环,该进程仍然没有退出:(请参阅我的更新。带有我的更改的脚本的修改版本将正确终止,至少在我的环境中是这样)。
for w in self.workers:
self.i_queue.put(None)
for w in self.workers:
w.join()