diff --git a/dvc/signal_handler.py b/dvc/signal_handler.py new file mode 100644 index 000000000..f900db0b4 --- /dev/null +++ b/dvc/signal_handler.py @@ -0,0 +1,17 @@ +import signal +import threading + +from dvc.logger import Logger + + +class SignalHandler(object): + def __enter__(self): + if isinstance(threading.current_thread(), threading._MainThread): + self.old_handler = signal.signal(signal.SIGINT, self.handler) + + def handler(self, sig, frame): + Logger.debug('Ignoring SIGINT during critical parts of code...') + + def __exit__(self, type, value, traceback): + if isinstance(threading.current_thread(), threading._MainThread): + signal.signal(signal.SIGINT, self.old_handler) diff --git a/dvc/state.py b/dvc/state.py index 43069f990..4f172e2c7 100644 --- a/dvc/state.py +++ b/dvc/state.py @@ -7,6 +7,8 @@ from dvc.lock import Lock from dvc.system import System from dvc.utils import file_md5, dict_md5, remove from dvc.exceptions import DvcException +from dvc.signal_handler import SignalHandler +from dvc.logger import Logger class StateEntry(object): @@ -96,14 +98,19 @@ class State(object): return {} with open(self.state_file, 'r') as fd: - return json.load(fd) + try: + return json.load(fd) + except ValueError as exc: + Logger.error('Failed to load \'{}\''.format(self.state_file), exc) + return {} def dump(self): if not self.state_file: return - with open(self.state_file, 'w+') as fd: - json.dump(self._db, fd) + with SignalHandler(): + with open(self.state_file, 'w+') as fd: + json.dump(self._db, fd) @staticmethod def mtime(path):