diff --git a/TorrentToMedia.py b/TorrentToMedia.py index 4b1ebfec..7ab5b551 100755 --- a/TorrentToMedia.py +++ b/TorrentToMedia.py @@ -297,7 +297,7 @@ def main(args): logger.info("The %s script completed successfully." % (args[0])) else: logger.error("A problem was reported in the %s script." % (args[0])) - + del nzbtomedia.MYAPP return result diff --git a/autoProcessMedia.cfg.spec b/autoProcessMedia.cfg.spec index 178bf799..8f4dda18 100644 --- a/autoProcessMedia.cfg.spec +++ b/autoProcessMedia.cfg.spec @@ -12,6 +12,7 @@ git_user = # GitHUB branch for repo git_branch = + # Enable/Disable forceful cleaning of leftover files following postprocess force_clean = 0 # Enable/Disable logging debug messages to nzbtomedia.log log_debug = 0 diff --git a/nzbToMedia.py b/nzbToMedia.py index 31c7ccf4..3296e1e5 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -722,12 +722,14 @@ def main(args, section=None): if result == 0: logger.info("The %s script completed successfully." % args[0]) if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 + del nzbtomedia.MYAPP return (nzbtomedia.NZBGET_POSTPROCESS_SUCCESS) else: logger.error("A problem was reported in the %s script." % args[0]) if os.environ.has_key('NZBOP_SCRIPTDIR'): # return code for nzbget v11 + del nzbtomedia.MYAPP return (nzbtomedia.NZBGET_POSTPROCESS_ERROR) - + del nzbtomedia.MYAPP return (result) diff --git a/nzbtomedia/__init__.py b/nzbtomedia/__init__.py index 656c2e6e..f8b847d2 100644 --- a/nzbtomedia/__init__.py +++ b/nzbtomedia/__init__.py @@ -4,6 +4,7 @@ import re import subprocess import sys import platform +import time # init libs PROGRAM_DIR = os.path.dirname(os.path.normpath(os.path.abspath(os.path.join(__file__, os.pardir)))) @@ -15,11 +16,13 @@ SYS_ARGV = sys.argv[1:] APP_FILENAME = sys.argv[0] APP_NAME = os.path.basename(APP_FILENAME) LOG_DIR = os.path.join(PROGRAM_DIR, 'logs') -LOG_FILE = os.path.join(LOG_DIR, 'postprocess.log') +LOG_FILE = os.path.join(LOG_DIR, 'nzbtomedia.log') +PID_FILE = os.path.join(LOG_DIR, 'nzbtomedia.pid') CONFIG_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMedia.cfg') CONFIG_SPEC_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMedia.cfg.spec') CONFIG_MOVIE_FILE = os.path.join(PROGRAM_DIR, 'autoProcessMovie.cfg') CONFIG_TV_FILE = os.path.join(PROGRAM_DIR, 'autoProcessTv.cfg') +MYAPP = None from nzbtomedia.autoProcess.autoProcessComics import autoProcessComics from nzbtomedia.autoProcess.autoProcessGames import autoProcessGames @@ -31,7 +34,7 @@ from nzbtomedia.nzbToMediaConfig import config from nzbtomedia.nzbToMediaUtil import category_search, sanitizeName, copy_link, parse_args, flatten, getDirs, \ rmReadOnly,rmDir, pause_torrent, resume_torrent, remove_torrent, listMediaFiles, \ extractFiles, cleanDir, update_downloadInfoStatus, get_downloadInfo, WakeUp, makeDir, cleanDir, \ - create_torrent_class, listMediaFiles + create_torrent_class, listMediaFiles, RunningProcess from nzbtomedia.transcoder import transcoder from nzbtomedia.databases import mainDB @@ -188,11 +191,16 @@ def initialize(section=None): NICENESS, LOG_DEBUG, FORCE_CLEAN, FFMPEG_PATH, FFMPEG, FFPROBE, AUDIOCONTAINER, EXTCONTAINER, TORRENT_CLASS, \ DELETE_ORIGINAL, PASSWORDSFILE, USER_DELAY, USER_SCRIPT, USER_SCRIPT_CLEAN, USER_SCRIPT_MEDIAEXTENSIONS, \ USER_SCRIPT_PARAM, USER_SCRIPT_RUNONCE, USER_SCRIPT_SUCCESSCODES, DOWNLOADINFO, CHECK_MEDIA, SAFE_MODE, \ - TORRENT_DEFAULTDIR, NZB_DEFAULTDIR, REMOTEPATHS, LOG_ENV + TORRENT_DEFAULTDIR, NZB_DEFAULTDIR, REMOTEPATHS, LOG_ENV, PID_FILE, MYAPP if __INITIALIZED__: return False + MYAPP = RunningProcess() + while MYAPP.alreadyrunning(): + print("!!! Waiting for existing session to end!") + time.sleep(30) + try: locale.setlocale(locale.LC_ALL, "") SYS_ENCODING = locale.getpreferredencoding() @@ -272,6 +280,9 @@ def initialize(section=None): updated = versionCheck.CheckVersion().update() if updated: # restart nzbToMedia + try: + del MYAPP + except: pass restart() else: logger.error("Update wasn't successful, not restarting. Check your log for more information.") diff --git a/nzbtomedia/logger.py b/nzbtomedia/logger.py index 5a318c8f..741d6ae9 100644 --- a/nzbtomedia/logger.py +++ b/nzbtomedia/logger.py @@ -242,7 +242,7 @@ class DispatchingFormatter: formatter = self._formatters.get(record.name, self._default_formatter) return formatter.format(record) -ntm_log_instance = NTMRotatingLogHandler("nzbtomedia.log", NUM_LOGS, LOG_SIZE) +ntm_log_instance = NTMRotatingLogHandler(nzbtomedia.LOG_FILE, NUM_LOGS, LOG_SIZE) def log(toLog, logLevel=MESSAGE, section='MAIN'): ntm_log_instance.log(toLog, logLevel, section) diff --git a/nzbtomedia/nzbToMediaUtil.py b/nzbtomedia/nzbToMediaUtil.py index 945e7975..6753d2ad 100644 --- a/nzbtomedia/nzbToMediaUtil.py +++ b/nzbtomedia/nzbToMediaUtil.py @@ -7,6 +7,7 @@ import struct import shutil import time import datetime +import platform import guessit import beets import requests @@ -932,4 +933,75 @@ def get_downloadInfo(inputName, status): sqlResults = myDB.select("SELECT * FROM downloads WHERE input_name=? AND status=?", [unicode(inputName), status]) - return sqlResults \ No newline at end of file + return sqlResults + +class RunningProcess(): + """ Limits application to single instance """ + + def __init__(self): + if platform.system() == 'Windows': + self.process = WindowsProcess() + else: + self.process = PosixProcess() + + def alreadyrunning(self): + return self.process.alreadyrunning() + + #def __del__(self): + # self.process.__del__() + +class WindowsProcess(): + + if platform.system() == 'Windows': + from win32event import CreateMutex + from win32api import CloseHandle, GetLastError + from winerror import ERROR_ALREADY_EXISTS + + def __init__(self): + self.mutexname = "nzbtomedia_{D0E858DF-985E-4907-B7FB-8D732C3FC3B9}" + + def alreadyrunning(self): + self.mutex = CreateMutex(None, False, self.mutexname) + self.lasterror = GetLastError() + return (self.lasterror == ERROR_ALREADY_EXISTS) + + def __del__(self): + if self.mutex: + CloseHandle(self.mutex) + +class PosixProcess(): + + def __init__(self): + self.pidpath = nzbtomedia.PID_FILE + + def alreadyrunning(self): + if os.path.exists(self.pidpath): + # Make sure it is not a "stale" pidFile + try: + pid = int(open(self.pidpath, 'r').read().strip()) + except: + pid = None + # Check list of running pids, if not running it is stale so overwrite + if isinstance(pid, int): + try: + os.kill(pid, 0) + self.lasterror = True + except OSError: + self.lasterror = False + else: + self.lasterror = False + else: + self.lasterror = False + + if not self.lasterror: + # Write my pid into pidFile to keep multiple copies of program from running + fp = open(self.pidpath, 'w') + fp.write(str(os.getpid())) + fp.close() + + return self.lasterror + + def __del__(self): + if not self.lasterror: + if os.path.isfile(self.pidpath): + os.unlink(self.pidpath)