Avoid concurrent config file writes

This commit is contained in:
kaso17
2017-01-05 18:08:10 +01:00
parent 175bea9269
commit 8e5538a11e

View File

@@ -28,6 +28,8 @@ namespace Jackett.Services
public class IndexerManagerService : IIndexerManagerService public class IndexerManagerService : IIndexerManagerService
{ {
private static readonly object configWriteLock = new object();
private IContainer container; private IContainer container;
private IConfigurationService configService; private IConfigurationService configService;
private Logger logger; private Logger logger;
@@ -177,59 +179,62 @@ namespace Jackett.Services
public void SaveConfig(IIndexer indexer, JToken obj) public void SaveConfig(IIndexer indexer, JToken obj)
{ {
var uID = Guid.NewGuid().ToString("N"); lock (configWriteLock)
var configFilePath = GetIndexerConfigFilePath(indexer); {
var configFilePathBak = configFilePath + ".bak"; var uID = Guid.NewGuid().ToString("N");
var configFilePathTmp = configFilePath + "." + uID + ".tmp"; var configFilePath = GetIndexerConfigFilePath(indexer);
var content = obj.ToString(); var configFilePathBak = configFilePath + ".bak";
var configFilePathTmp = configFilePath + "." + uID + ".tmp";
var content = obj.ToString();
logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp)); logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp));
if (string.IsNullOrWhiteSpace(content)) if (string.IsNullOrWhiteSpace(content))
{ {
throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID)); throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID));
} }
if (content.Contains("\x00")) if (content.Contains("\x00"))
{ {
throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content)); throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content));
} }
// make sure the config directory exists // make sure the config directory exists
if (!Directory.Exists(configService.GetIndexerConfigDir())) if (!Directory.Exists(configService.GetIndexerConfigDir()))
Directory.CreateDirectory(configService.GetIndexerConfigDir()); Directory.CreateDirectory(configService.GetIndexerConfigDir());
// create new temporary config file // create new temporary config file
File.WriteAllText(configFilePathTmp, content); File.WriteAllText(configFilePathTmp, content);
var fileInfo = new FileInfo(configFilePathTmp); var fileInfo = new FileInfo(configFilePathTmp);
if (fileInfo.Length == 0) if (fileInfo.Length == 0)
{ {
throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp)); throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp));
} }
// create backup file // create backup file
File.Delete(configFilePathBak); File.Delete(configFilePathBak);
if (File.Exists(configFilePath)) if (File.Exists(configFilePath))
{ {
try
{
File.Move(configFilePath, configFilePathBak);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString()));
}
}
// replace the actual config file
File.Delete(configFilePath);
try try
{ {
File.Move(configFilePath, configFilePathBak); File.Move(configFilePathTmp, configFilePath);
} }
catch (IOException ex) catch (IOException ex)
{ {
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString())); logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
} }
}
// replace the actual config file
File.Delete(configFilePath);
try
{
File.Move(configFilePathTmp, configFilePath);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
} }
} }