Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
2690c63d
Commit
2690c63d
authored
May 11, 2021
by
catch
Browse files
Issue
#3211936
by alexpott, daffie: Race condition when generating sub directories for image styles
parent
a9560b32
Changes
2
Hide whitespace changes
Inline
Side-by-side
core/lib/Drupal/Core/File/FileSystem.php
View file @
2690c63d
...
...
@@ -214,7 +214,10 @@ public function mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
$recursive_path
.
=
$component
;
if
(
!
file_exists
(
$recursive_path
))
{
if
(
!
$this
->
mkdirCall
(
$recursive_path
,
$mode
,
FALSE
,
$context
))
{
$success
=
$this
->
mkdirCall
(
$recursive_path
,
$mode
,
FALSE
,
$context
);
// If the operation failed, check again if the directory was created
// by another process/server, only report a failure if not.
if
(
!
$success
&&
!
file_exists
(
$recursive_path
))
{
return
FALSE
;
}
// Not necessary to use self::chmod() as there is no scheme.
...
...
core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php
View file @
2690c63d
...
...
@@ -5,6 +5,7 @@
use
Drupal\Component\FileSecurity\FileSecurity
;
use
Drupal\Component\FileSystem\FileSystem
;
use
Drupal\Component\Render\FormattableMarkup
;
use
Drupal\Core\Database\Database
;
use
Drupal\Core\File\Exception\FileException
;
use
Drupal\Core\File\FileSystemInterface
;
...
...
@@ -196,4 +197,51 @@ public function testDirectoryCreation() {
$this
->
assertTrue
(
$file_system
->
mkdir
(
$dir
.
'/foo/baz/'
,
0775
,
TRUE
));
}
/**
* Tests asynchronous directory creation.
*
* Image style generation can result in many calls to create similar directory
* paths. This test forks the process to create the same situation.
*/
public
function
testMultiplePrepareDirectory
()
{
if
(
!
function_exists
(
'pcntl_fork'
))
{
$this
->
markTestSkipped
(
'Requires the pcntl_fork() function'
);
}
$directories
=
[];
for
(
$i
=
1
;
$i
<=
10
;
$i
++
)
{
$directories
[]
=
'public://a/b/c/d/e/f/g/h/'
.
$i
;
}
$file_system
=
$this
->
container
->
get
(
'file_system'
);
$time_to_start
=
microtime
(
TRUE
)
+
0.1
;
// This loop creates a new fork to create each directory.
foreach
(
$directories
as
$directory
)
{
$pid
=
pcntl_fork
();
if
(
$pid
==
-
1
)
{
$this
->
fail
(
"Error forking"
);
}
elseif
(
$pid
==
0
)
{
// Sleep so that all the forks start preparing the directory at the same
// time.
usleep
((
$time_to_start
-
microtime
(
TRUE
))
*
1000000
);
$file_system
->
prepareDirectory
(
$directory
,
FileSystemInterface
::
CREATE_DIRECTORY
);
exit
();
}
}
// This while loop holds the parent process until all the child threads
// are complete - at which point the script continues to execute.
while
(
pcntl_waitpid
(
0
,
$status
)
!=
-
1
);
foreach
(
$directories
as
$directory
)
{
$this
->
assertDirectoryExists
(
$directory
);
}
// Remove the database connection because it will have been destroyed when
// the forks exited. This allows
// \Drupal\KernelTests\KernelTestBase::tearDown() to reopen it.
Database
::
removeConnection
(
'default'
);
}
}
catch
@catch
mentioned in commit
2f5eb025
·
May 11, 2021
mentioned in commit
2f5eb025
mentioned in commit 2f5eb02527e65cdb07ad121006a89177e2424a55
Toggle commit list
catch
@catch
mentioned in commit
220c6c9e
·
May 11, 2021
mentioned in commit
220c6c9e
mentioned in commit 220c6c9ee432b2b095733cab32c398181803d628
Toggle commit list
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment