fork进程与Threading之超时退出

将任务放置在子进程或其他线程中执行,在子进程或其他线程执行超时,则父进程或主线程程序并退出

fork进程

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"

Threading.Event

     全局定义了一个内置标志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)

 

原文地址:https://www.cnblogs.com/CaesarLinsa/p/11129702.html