Server issue Docker dev environment compatibility: account for faulty 9p filesystem driver

PaulB

Well-known member
Affected version
2.2.1
WSL2's 9p filesystem driver is faulty: http://github.com/microsoft/WSL/issues/5074

This can cause problems with cross-platform Docker-based devkits. While this is ultimately a problem that Microsoft needs to fix, there's a quick workaround that XenForo can implement to mitigate issues with cmd.php. Microsoft hasn't shown any sign of fixing the issue, so it would be helpful to have a workaround for now.

When invoking cmd.php while src is on a bridged volume using p9fs, inodes aren't fully enumerated. Repros can be a bit finicky, but the file for xf-dev:import has a tendency to be skipped, resulting in xf-dev:import being treated as a nonexistent command.

This is specific to development on Windows; I haven't run into this issue on macOS.

Workaround for XF\Cli\Runner#getValidCommandClasses:
PHP:
protected function getValidCommandClasses(array $directoryMap)
{
    $classes = [];

    foreach ($directoryMap AS $dir => $baseClass)
    {
        $fullPath = \XF\Util\File::canonicalizePath($dir);
        if (!file_exists($fullPath) || !is_dir($fullPath))
        {
            continue;
        }

        $files = [];
        $dirStack = [];

        for ($currentDir = $fullPath; $currentDir !== null; $currentDir = array_pop($dirStack))
        {
            foreach (scandir($currentDir) AS $baseName)
            {
                if ($baseName === '.' || $baseName === '..')
                {
                    continue;
                }

                $path = $currentDir . \XF::$DS . $baseName;

                if (0 === substr_compare($baseName, '.php', -4, 4))
                {
                    $files[] = $path;
                }
                else if (is_dir($path))
                {
                    $dirStack[] = $path;
                }
            }
        }

        foreach ($files AS $file)
        {
            $localPath = substr($file, strlen($fullPath));
            $localPath = trim(strtr($localPath, '\\', '/'), '/');

            $className = $baseClass . '\\' . strtr($localPath, '/', '\\');
            $className = substr($className, 0, -4);

            if ($this->isValidCommandClass($className))
            {
                $classes[] = $className;
            }
        }
    }

    return $classes;
}
 
Last edited:
This bug doesn't seem to trigger with glibc builds of PHP, even though the WSL bug report seems to indicate it's possible to reproduce with glibc. Switching from Alpine to Debian is a suitable workaround for now.
 
Ultimately, I don't think this is the sort of thing that we would generally intend to workaround.
 
Top Bottom