import os import time import signal # 信号数和stack框架 def chldhandler(signum, stackframe): """ signal handler.Runs on the parent and is called whenever a child terminates.""" while True: try: # -1 等待所有子进程 # os.WNOHANG(wait no hang)。如果没有子进程立即返回,如果子进程等待,返回进程pid的tuple # 退出信息 result = os.waitpid(-1, os.WNOHANG) except: break print "reaped child process %s" %result[0] # 第一个参数信号,第二个处理信号函数 signal.signal(signal.SIGCHLD, chldhandler) pid = os.fork() if pid: print "hello from the parent.the child pid is :%d" % pid print "sleeping 10 seconds" time.sleep(10) print "sleep done" else: print "child sleep 5 seconds" time.sleep(5)
fork一个子进程,当子进程早于父进程退出时,需要对子进程进行处理,否则子进程会变成zombie进程如下图,直到父进程执行完被清理之后,该子进程变为init的子进程,从而被清理。使用signal.signal(signal.SIGCHILD, chldhander),当子进程退出时,对子进程进行清理。
设计一个在子进程中执行某逻辑,子进程超时120秒,如果子进程在120秒内完成,则子进程清理后,父进程退出。否则,如果120秒没有完成,则使用kill,强制终止子进程,父进程退出。
# coding:utf-8 import os import time import signal flag = False # 信号数和stack框架 def chldhandler(signum, stackframe): """ signal handler.Runs on the parent and is called whenever a child terminates.""" while True: try: # -1 等待所有子进程 # os.WNOHANG(wait no hang)。如果没有子进程立即返回,如果子进程等待,返回进程pid的tuple # 退出信息 result = os.waitpid(-1, os.WNOHANG) global flag flag = True except: break print "reaped child process %s" %result[0] # 第一个参数信号,第二个处理信号函数 signal.signal(signal.SIGCHLD, chldhandler) pid = os.fork() if pid: print "hello from the parent.the child pid is :%d" % pid print "sleeping 120 seconds" for i in range(12): time.sleep(10) if flag: break if not flag: os.kill(pid, signal.SIGKILL) print "sleep done", pid else: print "child sleep 1 seconds" time.sleep(122) print "child sleep end"
全局定义了一个内置标志Flag,如果Flag值为 False,那么当程序执行 event.wait方法时就会阻塞,如果Flag值为True,那么event.wait 方法时便不再阻塞。
-
set() 将标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态
-
将标志设为False
-
isSet(): 获取内置标志状态,返回True或False
import threading import time event = threading.Event() def do_something(name): print("%s is read for do something" %name) event.wait() print("%s is doing" %name) thread1 = threading.Thread(target=do_something,args=('caesar',)) thread2 = threading.Thread(target=do_something,args=('ciro',)) threads = [] threads.append(thread1) threads.append(thread2) for thread in threads: thread.start() print("let's do together!") if not event.isSet(): event.set()
同理,使用主线程对其他线程监控,若其他线程执行do_something超时,则退出,若其他线程执行完成,主线程退出
import threading import time import sys event = threading.Event() def do_something(name): print("%s is read for do something" %name) print("%s is doing" %name) event.set() thread1 = threading.Thread(target=do_something,args=('caesar',)) thread1.start() for i in range(12): if not event.isSet(): time.sleep(10) if not event.isSet(): sys.exit(1) else: sys.exit(0)