diff --git a/src/File.php b/src/File.php index c9ee9e4..d1f9dae 100644 --- a/src/File.php +++ b/src/File.php @@ -59,11 +59,13 @@ public function truncate(int $size): void; /** * Makes a non-blocking attempt to lock the file. Returns true if the lock was obtained. * + * @throws FilesystemException If there is an error when attempting to lock the file. * @throws ClosedException If the file has been closed. */ public function lock(LockMode $mode): bool; /** + * @throws FilesystemException If there is an error when attempting to unlock the file. * @throws ClosedException If the file has been closed. */ public function unlock(): void; diff --git a/src/FileMutex.php b/src/FileMutex.php index ca22907..16124d6 100644 --- a/src/FileMutex.php +++ b/src/FileMutex.php @@ -2,11 +2,13 @@ namespace Amp\File; +use Amp\ByteStream\StreamException; use Amp\Cancellation; use Amp\Sync\Lock; use Amp\Sync\Mutex; use Amp\Sync\SyncException; use function Amp\delay; +use const Amp\Process\IS_WINDOWS; final class FileMutex implements Mutex { @@ -40,12 +42,19 @@ public function acquire(?Cancellation $cancellation = null): Lock for ($attempt = 0; true; ++$attempt) { try { $file = $this->filesystem->openFile($this->fileName, 'a'); - if ($file->lock(LockMode::Exclusive)) { - return new Lock(fn () => $this->release($file)); + + try { + if ($file->lock(LockMode::Exclusive)) { + return new Lock(fn () => $this->release($file)); + } + $file->close(); + } catch (FilesystemException|StreamException $exception) { + throw new SyncException($exception->getMessage(), previous: $exception); } - $file->close(); } catch (FilesystemException $exception) { - throw new SyncException($exception->getMessage(), previous: $exception); + if (!IS_WINDOWS) { // Windows fails to open the file if a lock is held. + throw new SyncException($exception->getMessage(), previous: $exception); + } } $multiplier = 2 ** \min(31, $attempt);