父服务器分支需要及时退出

时间:2014-01-14 06:31:12

标签: python fork exit

我有这个服务器草案,在新客户端连接后分叉新子节点。然后取决于客户端的命令子服务器在函数处理程序(连接)中做一些工作。

与此同时,我想停止父服务器,在此之前让父母等待所有工作的孩子。

问题是我应该在哪里为Ctrl+C键盘中断选项设置此信号功能。 signal.signal(signal.SIGINT,signal_handler)

children_list = []
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.bind((HOST, PORT))
conn.listen(5)
print("Listening on TCP port %s" % PORT)

def reaper(pids):   

        while children_list:                        
        pid,stat = os.waitpid(0, os.WNOHANG)   

        if not pid: 

            break

        pids.remove(pid)


def handler(connection):                    

    cmd = connection.recv(socksize)

def signal_handler(signal, frame):
    print 'You pressed Ctrl+C!'
    sys.exit(0)

def accept():                                

while 1:   
        global connection                                  
          connection, address = conn.accept()
          print "welcome new client!"
        reaper(children_list)
          pid = os.fork()                     
          if pid:#parent
              children_list.append(pid)
              connection.close()

         else:#child    
               handler(connection)


accept()

1 个答案:

答案 0 :(得分:0)

  

问题是我应该在何处为Ctrl + C键盘中断选项设置此信号功能。 signal.signal(signal.SIGINT,signal_handler)

您想要的任何地方,只要在您定义signal_handler之后和拨打accept之前。

我不确定信号处理程序实际上是你想要的。在大多数平台上,您实际正在做的事情会立即退出,就像您要求的那样,导致孩子们被重新定位到initlaunchd或类似物品。但你想要真正等待所有的孩子。因此,您无法拨打exit

在POSIX中,您不得在信号处理程序内拨打waitpid。 Python信号处理程序不是真正的信号处理程序,因此可能不相关 - 但我不认为这个事实在任何地方都可以保证。如果您想承担风险,可以尝试在signal_handler之前等待所有孩子,然后再致电exit,看看它是否适用于您的平台。

但是,标准的POSIX方法是让信号处理程序设置一些全局标志并返回。然后,主程序将从accept或其他正在等待的EINTR错误的其他阻塞调用中唤醒,此时它可以检查标志 - 如果为true,则等待孩子的时间并退出;否则,再次回到循环和accept

但无论如何所有这一切都不是必要的。默认的SIGINT处理程序应该只引发KeyboardInterrupt,这意味着 - 如果你没有安装自定义信号处理程序 - 你真正需要做的就是捕获该异常。换句话说,只需用最后一行替换:

try:
    accept()
except KeyboardInterrupt: # or maybe BaseException
    # wait for children, blocking instead of WNOHANG of course
    sys.exit(0)