import signal from logging.handlers import TimedRotatingFileHandler from multiprocessing import Process import time import os import errno import psutil import logging from threading import Thread # from Engine import logger import youtube_dl logger = logging.getLogger('log01') def wait_child(signum, frame): logger.debug('receive SIGCHLD') try: while True: # -1 表示任意子进程 # os.WNOHANG 表示如果没有可用的需要 wait 退出状态的子进程,立即返回不阻塞 cpid, status = os.waitpid(-1, os.WNOHANG) if cpid == 0: logger.debug('no child process was immediately available') break exitcode = status >> 8 logger.debug('child process %s exit with exitcode %s', cpid, exitcode) except OSError as e: if e.errno == errno.ECHILD: logger.error('current process has no existing unwaited-for child processes.') else: raise logger.debug('handle SIGCHLD end') def signal_handler(signum, frame): logger.info('收到Terminate:'+signum) raise youtube_dl.utils.DownloadError(frame) def kill_child_processes(parent_pid, file_name_, sig=signal.SIGINT): file_name_ = file_name_ + '.part' last_file_size = 0.0 while True: time.sleep(15) if os.path.isfile(file_name_): file_size = os.path.getsize(file_name_) / 1024 / 1024 / 1024 file_sizes = os.path.getsize(file_name_) if float(file_sizes) == last_file_size: try: parent = psutil.Process(parent_pid) except psutil.NoSuchProcess: return children = parent.children(recursive=True) if len(children) == 0: # parent.send_signal(sig) parent.terminate() logger.info('下载卡死pandaTV' + file_name_) else: for process in children: # print(process) # process.send_signal(sig) process.terminate() logger.info('下载卡死' + file_name_) # time.sleep(1) if os.path.isfile(file_name_): logger.info('卡死下载进程可能未成功退出') continue else: logger.info('卡死下载进程成功退出') break last_file_size = file_sizes if float(file_size) >= 2.5: try: parent = psutil.Process(parent_pid) except psutil.NoSuchProcess: return children = parent.children(recursive=True) if len(children) == 0: # parent.send_signal(sig) parent.terminate() logger.info('分段下载pandatv' + file_name_) else: for process in children: # print(process) # process.send_signal(sig) process.terminate() print('分段下载') logger.info('分段下载' + file_name_) break else: logger.info('监控线程退出') return # os._exit(0) logger.info('退出监控线程') def monitoring(q): # signal.signal(signal.SIGCHLD, wait_child) while True: # print('开始监测') pid, file_name = q.get() time.sleep(5) logger.info('获取到{0},{1}'.format(pid, file_name)) t = Thread(target=kill_child_processes, args=(pid, file_name)) t.start() def new_hook(t, v, tb): logger.error("Uncaught exception:", exc_info=(t, v, tb)) class SafeRotatingFileHandler(TimedRotatingFileHandler): def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False): TimedRotatingFileHandler.__init__(self, filename, when, interval, backupCount, encoding, delay, utc) """ Override doRollover lines commanded by "##" is changed by cc """ def doRollover(self): """ do a rollover; in this case, a date/time stamp is appended to the filename when the rollover happens. However, you want the file to be named for the start of the interval, not the current time. If there is a backup count, then we have to get a list of matching filenames, sort them and remove the one with the oldest suffix. Override, 1. if dfn not exist then do rename 2. _open with "a" model """ if self.stream: self.stream.close() self.stream = None # get the time that this sequence started at and make it a TimeTuple currentTime = int(time.time()) dstNow = time.localtime(currentTime)[-1] t = self.rolloverAt - self.interval if self.utc: timeTuple = time.gmtime(t) else: timeTuple = time.localtime(t) dstThen = timeTuple[-1] if dstNow != dstThen: if dstNow: addend = 3600 else: addend = -3600 timeTuple = time.localtime(t + addend) dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple) ## if os.path.exists(dfn): ## os.remove(dfn) # Issue 18940: A file may not have been created if delay is True. ## if os.path.exists(self.baseFilename): if not os.path.exists(dfn) and os.path.exists(self.baseFilename): os.rename(self.baseFilename, dfn) if self.backupCount > 0: for s in self.getFilesToDelete(): os.remove(s) if not self.delay: self.mode = "a" self.stream = self._open() newRolloverAt = self.computeRollover(currentTime) while newRolloverAt <= currentTime: newRolloverAt = newRolloverAt + self.interval # If DST changes and midnight or weekly rollover, adjust for this. if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc: dstAtRollover = time.localtime(newRolloverAt)[-1] if dstNow != dstAtRollover: if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour addend = -3600 else: # DST bows out before next rollover, so we need to add an hour addend = 3600 newRolloverAt += addend self.rolloverAt = newRolloverAt