0f8a764a44
Introduces an exclusive file lock (FileShare.None on wallet.json.lock) held for the duration of a wallet session. A second instance trying to open the same file receives null from TryAcquire and sees a localized error message; UnauthorizedAccessException (OS permission issues) propagates separately so the UI can show a distinct message. The .lock file is deleted on Dispose (best-effort); the real guard is the open FileStream, which the OS releases automatically on crash.
49 lines
1.4 KiB
C#
49 lines
1.4 KiB
C#
namespace PalladiumWallet.Core.Storage;
|
|
|
|
/// <summary>
|
|
/// Exclusive lock on a wallet file held for the lifetime of the session.
|
|
/// The real lock is the open FileStream with FileShare.None — the .lock file
|
|
/// is just its vessel. The OS releases it automatically on process exit or crash.
|
|
/// </summary>
|
|
public sealed class WalletLock : IDisposable
|
|
{
|
|
private readonly string _lockPath;
|
|
private FileStream? _stream;
|
|
|
|
private WalletLock(string lockPath, FileStream stream)
|
|
{
|
|
_lockPath = lockPath;
|
|
_stream = stream;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to acquire an exclusive lock for <paramref name="walletPath"/>.
|
|
/// Returns null if another process already holds the lock (IOException).
|
|
/// Lets UnauthorizedAccessException propagate so callers can show a distinct message.
|
|
/// </summary>
|
|
public static WalletLock? TryAcquire(string walletPath)
|
|
{
|
|
var lockPath = walletPath + ".lock";
|
|
try
|
|
{
|
|
var stream = new FileStream(
|
|
lockPath,
|
|
FileMode.OpenOrCreate,
|
|
FileAccess.ReadWrite,
|
|
FileShare.None);
|
|
return new WalletLock(lockPath, stream);
|
|
}
|
|
catch (IOException)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_stream?.Dispose();
|
|
_stream = null;
|
|
try { File.Delete(_lockPath); } catch { }
|
|
}
|
|
}
|