phpfile-put-contents

php file_put_contents no such file or directory occasionally


I start 8 processes to execute a job, the code in the job like this:

<?php
$dir = "/home/test/fileputcontents/0";
if(! is_dir($dir)){
    mkdir($dir, 0755, true);
}
file_put_contents("{$dir}/0.txt", "aaaa\n", FILE_APPEND | LOCK_EX);

but it raises an error which say "No such file or directory" sometimes,not very offen, thanks very much.

Is it because php_mkdir_ex method? Multi-process create directory at the same time.

/* DEPRECATED APIs: Use php_stream_mkdir() instead */
PHPAPI int php_mkdir_ex(const char *dir, zend_long mode, int options)
{
    int ret;

    if (php_check_open_basedir(dir)) {
        return -1;
    }

    if ((ret = VCWD_MKDIR(dir, (mode_t)mode)) < 0 && (options & REPORT_ERRORS)) {
        php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
    }

    return ret;
}

Solution

  • Finally, I found the reason from php source code. It's because the directory creation collision. For example:

    1. We have 2 processes to create directory "/home/test/fileputcontents/0" at the same time.
    2. Now only /home directory exists, we need create test/fileputcontents/0
    3. One process (we call A) has created test, is going to create fileputcontents,anther process (we call B) is going to create test again, but it already exists.
    4. Then process B stopping creating directory, because it thinks all directories exist
    5. When B tries to call file_put_contents before A creates all the directories, then it warns "No such file or directory", because fileputcontents/0 does not exist.

    My solution, create directories because processes start.