[Filesystem] improve error handling in lock()

This commit is contained in:
Christian Flothmann 2017-05-25 11:59:42 +02:00
parent 49d6604ee4
commit 25381a2809
2 changed files with 46 additions and 3 deletions

View File

@ -68,8 +68,12 @@ class LockHandler
return true;
}
$error = null;
// Silence error reporting
set_error_handler(function () {});
set_error_handler(function ($errno, $msg) use (&$error) {
$error = $msg;
});
if (!$this->handle = fopen($this->file, 'r')) {
if ($this->handle = fopen($this->file, 'x')) {
@ -82,8 +86,7 @@ class LockHandler
restore_error_handler();
if (!$this->handle) {
$error = error_get_last();
throw new IOException($error['message'], 0, null, $this->file);
throw new IOException($error, 0, null, $this->file);
}
// On Windows, even if PHP doc says the contrary, LOCK_NB works, see

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\Filesystem\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\LockHandler;
class LockHandlerTest extends TestCase
@ -40,6 +42,44 @@ class LockHandlerTest extends TestCase
new LockHandler('lock', '/');
}
public function testErrorHandlingInLockIfLockPathBecomesUnwritable()
{
// skip test on Windows; PHP can't easily set file as unreadable on Windows
if ('\\' === DIRECTORY_SEPARATOR) {
$this->markTestSkipped('This test cannot run on Windows.');
}
$lockPath = sys_get_temp_dir().'/'.uniqid();
$e = null;
$wrongMessage = null;
try {
mkdir($lockPath);
$lockHandler = new LockHandler('lock', $lockPath);
chmod($lockPath, 0444);
$lockHandler->lock();
} catch (IOException $e) {
if (false === strpos($e->getMessage(), 'Permission denied')) {
$wrongMessage = $e->getMessage();
} else {
$this->addToAssertionCount(1);
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
}
if (is_dir($lockPath)) {
$fs = new Filesystem();
$fs->remove($lockPath);
}
$this->assertInstanceOf('Symfony\Component\Filesystem\Exception\IOException', $e, sprintf('Expected IOException to be thrown, got %s instead.', get_class($e)));
$this->assertNull($wrongMessage, sprintf('Expected exception message to contain "Permission denied", got "%s" instead.', $wrongMessage));
}
public function testConstructSanitizeName()
{
$lock = new LockHandler('<?php echo "% hello word ! %" ?>');