天天看点

python简单程序使用signal模块处理僵死进程

程序一:未使用信号处理程序

#! /usr/bin/python
import socket, os

"""
   简单网络程序,每次连接后派生的子进程终止后都会成为僵死进程
"""

serSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serSock.bind(("", 8888))
serSock.listen(5)

while True:
     conn, addr = serSock.accept()
     pid = os.fork()
     if pid:
         """
            父进程关闭子进程的已连接套接字
         """
        conn.close()
        continue
     elif pid == 0:
         """
            子进程关闭父进程的监听套接字
         """
        serSock.close()
        data = conn.recv(1024)
        conn.sendall("echo: "+data)
        conn.close()
        os._exit(0)
           
python简单程序使用signal模块处理僵死进程

上图明显可见父进程的几个僵死子进程

程序二:使用信号处理程序

#! /usr/bin/python
import signal, socket, os

"""
   信号处理函数,waitpid获取终止子进程的某些信息,但这里我们不关注,所以未定义返回值
"""
def signal_handler(num):
    while not (waitpid(-1, os.WNOHANG)):
          return


"""
   安装信号处理函数
"""
signal.signal(signal.SIGCHLD, signal_handler)
"""signal.signal(signal.SIGCHD, signal_handler)"""

"""
   某些会阻塞的系统调用会被在信号处理程序返回后被中断,这里处于各个平台的兼容性考虑,我们手动重启被中断的系统调用
"""
signal.siginterrupt(signal.SIGCHLD, False)
"""signal.siginterrupt(signal.SIGCHD, False)"""



serSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serSock.bind(("", 8888))
serSock.listen(5)

while True:
     conn, addr = serSock.accept()
     pid = os.fork()
     if pid:
        conn.close()
        continue
     elif pid == 0:
        serSock.close()
        data = conn.recv(1024)
        conn.sendall("echo: "+data)
        conn.close()
        os._exit(0)
           

程序三:使用multiprocessing.Processing代替os.fork

#! /usr/bin/python
import multiprocessing, socket, time

def handler(conn, serSock):
    serSock.close()
    data = conn.recv(1024)
    conn.sendall("echo: " + data)


serSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serSock.bind(("", 9999))
serSock.listen(5)

while True:
      conn, addr = serSock.accept()
      childProcess = multiprocessing.Process(target=handler, args=(conn, serSock))
      childProcess.start()
      conn.close()
           

开启三个客户端与服务器相连,截图如下:

python简单程序使用signal模块处理僵死进程

可以明显看到三个派生的子进程

现在依次断开三个客户端的连接,使得派生子进程终止,截图如下:

python简单程序使用signal模块处理僵死进程

这里出现第一个僵死进程

python简单程序使用signal模块处理僵死进程

这里出现第二个僵死进程

python简单程序使用signal模块处理僵死进程

这里出现第三个僵死进程

再建立一次连接:

python简单程序使用signal模块处理僵死进程

发现原先的僵死进程被清除了 不过这次连接断开后仍然会出现一次僵死进程 不过阀体可以知道multiprocessing.Process自行处理僵死进程,不用想os.fork那样自己建立信号处理程序、安装信号处理程序