Search code examples
phpdirectoryphp-5.4

Is is_dir() unreliable, or are there race conditions that can be mitigated here?


At work, I've inherited a web application that has a file upload process. Part of this process occasionally (once every two weeks or so) triggers the following error:

PHP Warning:  mkdir(): File exists in {{{file_path_name_redacted}}} on line 7

Looking at lines 6-8, gives us:

if(!is_dir($storeFolder)){
    mkdir($storeFolder, 0644, TRUE);
}

Given this file can be hit by multiple PHP processes, I believe race conditions may be coming into play here. I've seen the same problem on other sites that I've managed in the past, similarly occurring only once in a blue moon.

What I believe is happening is that users are double-clicking on the upload button, which causes two PHP processes to execute at almost exactly the same time, like this:

Process 1 executes line 6 - dir does not exist
Process 2 executes line 6 - dir does not exist
Process 1 executes line 7 - directory is created
Process 2 executes line 7 - directory cannot be created as it already exists

Is this a case of race conditions, as I explained above (i.e. has anyone else noticed this), and/or is there some way of mitigating the error other turning off error reporting for warnings?


Solution

  • Php inspections confirms that a race condition exists, and suggests that the safest way to write your code is:

    if (!is_dir($dir) && !mkdir($dir) && !is_dir($dir)) {
        throw new \RuntimeException(sprintf('Directory "%s" could not be created', $dir));
    }
    

    A bit more of explanation   (Edit: link is dead see link above)

    It feels strange, but it certainly works. Best of luck.