state: protect from SIGINT and corruption

Fixes #814

Signed-off-by: Ruslan Kuprieiev <[email protected]>
This commit is contained in:
Ruslan Kuprieiev
2018-06-28 17:08:42 +03:00
parent 3a1a5f84a8
commit 5f8f199958
2 changed files with 27 additions and 3 deletions
+17
View File
@@ -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)
+10 -3
View File
@@ -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):