Software engineering notes

PHP atomic write function

with 7 comments

Motivation:

An atomic write function for those who appreciate the convenience of file_put_contents(), but need an atomic operation.  Please leave a comment if you have a more convenient and/or efficient solution.

Update (5/31/11):

Now using flock, as recommended by Petr and Hayden in their comments below, to avoid race condition. Thanks for the help!

Source code:


function atomic_put_contents($filename, $data)
{
    // Copied largely from http://php.net/manual/en/function.flock.php
    $fp = fopen($filename, "w+");
    if (flock($fp, LOCK_EX)) {
        fwrite($fp, $data);
        flock($fp, LOCK_UN);
    }
    fclose($fp);
}

Example usage:


$content = 'some content';

atomic_put_contents('path/file.ext', $content);

//creates file called path/file.ext containing 'some content'

Written by Erik

October 26, 2008 at 1:58 am

Posted in code

Tagged with

7 Responses

Subscribe to comments with RSS.

  1. Is a good solution?
    Function “exec” ordinarily not available on a web-hostings, but PHP have atomic and fast function and this is rename which atomic work only the same partition. Not only write to file must be atomic, but read too. check http://cz2.php.net/function.stream_wrapper_register
    http://php.net/function.flock

    Petr Kramář

    June 7, 2009 at 10:26 pm

    • thanks, Petr! I don’t have any experience w/ flock, but I’ll take a look at it. I heard writing and mv-ing a file was a simple, effective method for manipulating a file atomically, and it’s worked for my humble needs, but I’d prefer to use something more standard.

      erikeldridge

      June 12, 2009 at 10:02 am

  2. This code has race conditions. It is possible that the file $tmp_path will be removed by another process after line 10, but before line 13. If you truly need atomicity, use flock() as Petr suggested.

    Hayden

    April 13, 2011 at 2:57 pm

    • Thanks, Hayden. I’ve updated the function to use flock.

      Erik

      May 31, 2011 at 9:05 pm

  3. I realize this post is quite old but in case anyone else ends up here:

    I believe fopen using w+ will truncate the file, even if you don’t get the lock, so I think you could truncate a file that someone else is reading (assuming it’s not locked)?, it might be better to use mode “c” or “c+”? You probably then need to truncate with ftruncate unless you’re sure the contents are less or equal to what you’re writing

    Tim

    September 11, 2015 at 8:24 pm

  4. You must use “c” with ftruncate instead of using “w+”, otherwise it’s not really atomic because another request can see an empty file for a moment (or corrupted?), even using flock.

    function atomic_put_contents($filename, $data)
    {
    // Copied largely from http://php.net/manual/en/function.flock.php
    if(($fp = fopen($filename, “c”)) !== false)
    {
    if (flock($fp, LOCK_EX))
    return ftruncate($fp, 0) && fwrite($fp, $data) !== false && flock($fp, LOCK_UN) && fclose($fp);
    }

    return false;
    }
    //Removed the else from my previous post

    Marcelo Cruz

    May 16, 2019 at 12:15 pm

  5. After php 5.1.0 you can just use file_put_contents($filename, $data, LOCK_EX);

    Marcelo Cruz

    May 16, 2019 at 12:22 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: