diff --git a/miscDeps b/miscDeps index 48109d94c67..e7db1066486 160000 --- a/miscDeps +++ b/miscDeps @@ -1 +1 @@ -Subproject commit 48109d94c6741a0c57a03183b6bf5963e31469d2 +Subproject commit e7db10664865f5f54c8b4671aa78c84afd82017a diff --git a/source/config/__init__.py b/source/config/__init__.py index 41a1242d053..9a4444df0a9 100644 --- a/source/config/__init__.py +++ b/source/config/__init__.py @@ -6,6 +6,7 @@ import ctypes import ctypes.wintypes import os +import osreplace import sys from cStringIO import StringIO import itertools @@ -17,6 +18,7 @@ import shlobj import baseObject import easeOfAccess +from fileUtils import FaultTolerantFile import winKernel def validateConfig(configObj,validator,validationResult=None,keyList=None): @@ -638,10 +640,12 @@ def save(self): # Never save the config if running securely. return try: - self.profiles[0].write() + with FaultTolerantFile(self.profiles[0].filename) as f: + self.profiles[0].write(f) log.info("Base configuration saved") for name in self._dirtyProfiles: - self._profileCache[name].write() + with FaultTolerantFile(self._profileCache[name].filename) as f: + self._profileCache[name].write(f) log.info("Saved configuration profile %s" % name) self._dirtyProfiles.clear() except Exception as e: @@ -738,7 +742,7 @@ def renameProfile(self, oldName, newName): if oldName.lower() != newName.lower() and os.path.isfile(newFn): raise ValueError("A profile with the same name already exists: %s" % newName) - os.rename(oldFn, newFn) + osreplace.replace(oldFn, newFn) # Update any associated triggers. allTriggers = self.triggersToProfiles saveTrigs = False diff --git a/source/fileUtils.py b/source/fileUtils.py new file mode 100644 index 00000000000..8a26cf9bcf8 --- /dev/null +++ b/source/fileUtils.py @@ -0,0 +1,16 @@ +import os +import osreplace +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from logHandler import log + +@contextmanager +def FaultTolerantFile(name): + dirpath, filename = os.path.split(name) + with NamedTemporaryFile(dir=dirpath, prefix=filename, suffix='.tmp', delete=False) as f: + log.debug(f.name) + yield f + f.flush() + os.fsync(f) + f.close() + osreplace.replace(f.name, name) \ No newline at end of file diff --git a/source/inputCore.py b/source/inputCore.py index 962600c2aa0..179b875b3ce 100644 --- a/source/inputCore.py +++ b/source/inputCore.py @@ -23,6 +23,7 @@ import speech import characterProcessing import config +from fileUtils import FaultTolerantFile import watchdog from logHandler import log import globalVars @@ -359,7 +360,8 @@ def save(self): else: outSect[script] = [outVal, gesture] - out.write() + with FaultTolerantFile(out.filename) as f: + out.write(f) class InputManager(baseObject.AutoPropertyObject): """Manages functionality related to input from the user.