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?
A race condition can only occur between two or more threads / external state (one of them can be the OS). We cannot have race conditions inside a single thread process, non I/O doing program.
A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread reads the same value from the variable.
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
It feels strange, but it certainly works. Best of luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With