Skip to content

Conversation

@bugalot
Copy link

@bugalot bugalot commented Apr 10, 2018

Basically, the goal is to solve the following issue. It's kind of a moving target as the entire solar system must be aligned to reproduce this issue. Fortunately, the following scripts will help you to reproduce the issue quite easily (put all of them in the same directory).

The PR here basically implements to same logic as in the mkdirfixretry.php script. An extra check regarding the FlySystem implementation to make sure the use of umask will not interfer with further writes.

rmdir.php
Simply removes folder a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z. The directory must NOT BE THERE prior launching mkdir.php in order to reproduce the bug. So do not forget to run rmdir.php first.

<?php
function rrmdir($dir) { 
   if (is_dir($dir)) { 
     $objects = scandir($dir); 
     foreach ($objects as $object) { 
       if ($object != "." && $object != "..") { 
         if (is_dir($dir."/".$object))
           rrmdir($dir."/".$object);
         else
           unlink($dir."/".$object); 
       } 
     }
     rmdir($dir); 
   } 
 }

@rrmdir('a');

mkdir.php
Use this script to reproduce the bug (make sure you ran rmdir.php before). You will see some failures at the very beginning of the script, when "everybody is forking like hell". After that, the situation gets better (press CTRL-C to interrupt).

<?php
$dir = 'a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z';

echo "forking...\n";
$pid = pcntl_fork();
echo "forking...\n";
$pid = pcntl_fork();
echo "forking...\n";
$pid = pcntl_fork();

$count = 0;
while (true) {
    $umask = umask(0);
    @mkdir($dir, 0775, true);
    umask($umask);
    
    if (!is_dir($dir) || !is_writable($dir)) {
        echo getmypid() . " - FAILURE AT ${count}!!!!!\n";
    }
    
    $count++;
    
    if ($count % 1000 === 0) {
        echo getmypid() . " - ${count} directories created!\n";
    }
    
    usleep(1);
}

mkdirfixretry.php
Use this script to validate the approach. You should not see any failures, just retries. Make sure you ran rmdir.php before running the test.

<?php
$dir = 'a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z';
echo "forking...\n";
pcntl_fork();
echo "forking...\n";
pcntl_fork();
echo "forking...\n";
pcntl_fork();

$count = 0;
while (true) {
    $attempts = 3;
    $i = 0;
    while ($i < $attempts) {
        $umask = umask(0);
        @mkdir($dir, 0775, true);
        umask($umask);
        
        if (is_dir($dir) && is_writable($dir)) {
            break;
        } else {
            echo getmypid() . " - RETRY ${i}!!!\n";
            usleep(10);
        }
        
        $i++;
    }
    
    if ($i >= $attempts) {
        echo getmypid() . " - FAILURE AT ${count}!\n";
    }
    
    $count++;
    
    if ($count % 1000 === 0) {
        echo getmypid() . " - ${count} directories created!\n";
    }
    
    usleep(1);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants