Browse Source

Use a Mutex when accessing SharpDevelopProperties.xml

Prevents IOException when shutting down multiple SharpDevelop instances at the same time.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4029 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
02b0d47d15
  1. 1
      src/Main/Core/Project/ICSharpCode.Core.csproj
  2. 42
      src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs
  3. 35
      src/Main/Core/Project/Src/Util/CallbackOnDispose.cs

1
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -99,6 +99,7 @@ @@ -99,6 +99,7 @@
<Compile Include="Src\Services\StringParser\IStringTagProvider.cs" />
<Compile Include="Src\Services\StringParser\StringParser.cs" />
<Compile Include="Src\Util\AbstractCommand.cs" />
<Compile Include="Src\Util\CallbackOnDispose.cs" />
<Compile Include="Src\Util\DebugTextWriter.cs" />
<Compile Include="Src\Util\ICommand.cs" />
<Compile Include="Src\AddInTree\AddIn\IBuildItemsModifier.cs" />

42
src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Xml;
namespace ICSharpCode.Core
@ -90,12 +91,14 @@ namespace ICSharpCode.Core @@ -90,12 +91,14 @@ namespace ICSharpCode.Core
return false;
}
try {
using (XmlTextReader reader = new XmlTextReader(fileName)) {
while (reader.Read()){
if (reader.IsStartElement()) {
if (reader.LocalName == propertyXmlRootNodeName) {
properties.ReadProperties(reader, propertyXmlRootNodeName);
return true;
using (LockPropertyFile()) {
using (XmlTextReader reader = new XmlTextReader(fileName)) {
while (reader.Read()){
if (reader.IsStartElement()) {
if (reader.LocalName == propertyXmlRootNodeName) {
properties.ReadProperties(reader, propertyXmlRootNodeName);
return true;
}
}
}
}
@ -108,15 +111,38 @@ namespace ICSharpCode.Core @@ -108,15 +111,38 @@ namespace ICSharpCode.Core
public static void Save()
{
string fileName = Path.Combine(configDirectory, propertyFileName);
using (XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8)) {
using (MemoryStream ms = new MemoryStream()) {
XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
writer.Formatting = Formatting.Indented;
writer.WriteStartElement(propertyXmlRootNodeName);
properties.WriteProperties(writer);
writer.WriteEndElement();
writer.Flush();
ms.Position = 0;
string fileName = Path.Combine(configDirectory, propertyFileName);
using (LockPropertyFile()) {
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) {
ms.WriteTo(fs);
}
}
}
}
/// <summary>
/// Acquires an exclusive lock on the properties file so that it can be opened safely.
/// </summary>
public static IDisposable LockPropertyFile()
{
Mutex mutex = new Mutex(false, "PropertyServiceSave-30F32619-F92D-4BC0-BF49-AA18BF4AC313");
mutex.WaitOne();
return new CallbackOnDispose(
delegate {
mutex.ReleaseMutex();
mutex.Close();
});
}
static void PropertiesPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null) {

35
src/Main/Core/Project/Src/Util/CallbackOnDispose.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Threading;
namespace ICSharpCode.Core
{
/// <summary>
/// Invokes a callback when this class is dispsed.
/// </summary>
sealed class CallbackOnDispose : IDisposable
{
// TODO: in 4.0, use System.Action and make this class public
System.Threading.ThreadStart callback;
public CallbackOnDispose(System.Threading.ThreadStart callback)
{
if (callback == null)
throw new ArgumentNullException("callback");
this.callback = callback;
}
public void Dispose()
{
System.Threading.ThreadStart action = Interlocked.Exchange(ref callback, null);
if (action != null)
action();
}
}
}
Loading…
Cancel
Save