2009-06-20 7 views
4

다른 여러 하위 프로세스를 생성하는 데몬 프로그램을 작성 중입니다. 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 서버 프로세스) 잘 종료하지만 주요 과정은 그냥 유지 그것은 돌아 오지 않는다.

+0

"종료 중 ..."이 인쇄되어 있습니까? – grieve

+1

나는 당신의 코드를 그대로 놔두고, 데몬 모듈을 빼고 나에게 도움이되었다. 데몬 모듈의 버전에 대한 링크를 줄 수 있습니까? Google 검색은 몇 가지 선택을 보여줍니다. – grieve

+0

늦은 응답으로 죄송합니다. http://pypi.python.org/pypi/python-daemon/ – btw0

답변

1

나는 다른 접근법을 시도했는데 이것이 작동하는 것처럼 보였다. (필자는 모듈을 설치하지 않았기 때문에 코드의 데몬 부분을 꺼냈다.)

import signal 

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): 

     # all your code minus the loop 

     print "waiting to die" 

     signal.pause() 

    def stop(self): 
     print "quitting ..." 

     # all your code minus self.running 


manager = Manager() 

signal.signal(signal.SIGHUP, lambda signum, frame: manager.stop()) 

manager.start() 

한 경고는, 어떤 신호를 일시 중지를 해제 것 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() 

사용하는 파이썬의 버전은 무엇?

+0

직접 신호 처리를하지 않습니다. http://pypi.python.org/pypi/python-daemon/ – btw0

1

http 서버 프로세스를 만들지 만 join()은 생성하지 않습니다. http 서버 프로세스를 중지하기 위해 os.kill()을 수행하는 대신, 직원에게 보내는 것처럼 None과 같은 중지 처리 센티널을 보낸 다음 self.http.join()을 수행하면 어떻게됩니까?

업데이트 : 당신은 각 근로자의 입력 큐 번 None 감시를 보내야합니다. 시도해 볼 수 있습니다 :

for w in self.workers: 
     self.i_queue.put(None) 
    for w in self.workers: 
     w.join() 

N.B. 두 개의 루프가 필요한 이유는 을 join()과 동일한 루프의 대기열에 넣으면 w 이외의 작업자가 None을 수신 할 수 있으므로 w에 가입하면 호출자가 차단됩니다.

작업자 또는 http 서버에 대한 코드를 표시하지 않으므로 task_done 등을 호출하는 측면에서 정상적으로 작동하며 각 작업자가 None을보고 즉시 종료한다고 가정합니다. get()-ing 더 이상 입력 큐의 내용.

또한 적어도 one open, hard-to-reproduce issue에는 JoinableQueue.task_done()이 포함되어있어 물어 뜯을 수 있습니다.

+0

에서 데몬 모듈을 다루었습니다. while while true loop while my own.http.join(),하지만 하나의 프로세스가 종료되지 않은 다음, 나는 진실한 루프로 대체했다. 프로세스는 여전히 종료되지 않는다. ( – btw0

+0

내 업데이트보기. 내 변경 사항이있는 스크립트의 수정 된 버전이 적어도 내 환경에서는 올바르게 종료된다. . –