cleanup shared lock if changing to exclusive lock failed

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2019-01-22 15:32:48 +01:00 committed by Backportbot
parent e898c52eb0
commit 9126cdc7a8
2 changed files with 38 additions and 1 deletions

View File

@ -1139,7 +1139,13 @@ class View {
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($run and $storage) {
if (in_array('write', $hooks) || in_array('delete', $hooks)) {
$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
try {
$this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
} catch (LockedException $e) {
// release the shared lock we acquired before quiting
$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
throw $e;
}
}
try {
if (!is_null($extraParam)) {

View File

@ -1987,6 +1987,37 @@ class ViewTest extends \Test\TestCase {
$this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception');
}
public function testLockBasicOperationUnlocksAfterLockException() {
$view = new View('/' . $this->user . '/files/');
$storage = new Temporary([]);
Filesystem::mount($storage, array(), $this->user . '/');
$storage->mkdir('files');
$storage->mkdir('files/dir');
$storage->file_put_contents('files/test.txt', 'blah');
$storage->getScanner()->scan('files');
// get a shared lock
$handle = $view->fopen('test.txt', 'r');
$thrown = false;
try {
// try (and fail) to get a write lock
$view->unlink('test.txt');
} catch (\Exception $e) {
$thrown = true;
$this->assertInstanceOf(LockedException::class, $e);
}
$this->assertTrue($thrown, 'Exception was rethrown');
// clean shared lock
fclose($handle);
$this->assertNull($this->getFileLockType($view, 'test.txt'), 'File got unlocked');
}
/**
* Test locks for fopen with fclose at the end
*