[ACCEPTED]-Most reliable & safe method of preventing race conditions in PHP-concurrency

Accepted answer
Score: 12

In fact, i think there is no need for a 16 complex mutex / semaphore whatever solution.

Form 15 keys stored in a PHP $_SESSION are all you need. As 14 a nice side effect, this method also protects 13 your form against CSRF attacks.

In PHP, sessions 12 are locked and session_start() waits until the user session 11 is released. You just have to unset() the form 10 key on the first valid request. The second 9 request has to wait until the first one 8 releases the session.

However, when running 7 in a (not session or source ip based) load 6 balancing scenario things are getting more 5 complicated. For such a scenario, i'm sure 4 you will find a valuable solution in this 3 great paper: http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/

I reproduced your use case 2 with the following demonstration. just throw 1 this file onto your webserver and test it:

<?php
session_start();
if (isset($_REQUEST['do_stuff'])) {
  // do stuff
  if ($_REQUEST['uniquehash'] == $_SESSION['uniquehash']) {
    echo "valid, doing stuff now ... "; flush();
    // delete formkey from session
    unset($_SESSION['uniquehash']);
    // release session early - after committing the session data is read-only
    session_write_close();
    sleep(20);  
    echo "stuff done!";
  }
  else {
    echo "nope, {$_REQUEST['uniquehash']} is invalid.";
  }     
}
else {
  // show form with formkey
  $_SESSION['uniquehash'] = md5("foo".microtime().rand(1,999999));
?>
<html>
<head><title>session race condition example</title></head>
<body>
  <form method="POST">
    <input type="hidden" name="PHPSESSID" value="<?=session_id()?>">
    <input type="text" name="uniquehash" 
      value="<?= $_SESSION['uniquehash'] ?>">
    <input type="submit" name="do_stuff" value="Do stuff!">
  </form>
</body>
</html>
<?php } ?>
Score: 3

An interesting question you have but you 13 don't have any data or code to show.

For 12 80% of cases the chances of anything nasty 11 happening because of PHP itself are virtually 10 zero if you follow the standard procedures 9 and practices regarding stopping users from 8 submitting forms multiple times, which applies 7 to nearly every other setup, not just PHP.

If 6 you're the 20% and your environment demands 5 it, then one option is using message queues 4 which I'm sure you are familiar with. Again, this 3 idea is language agnostic. Nothing to do 2 with languages. Its all about how data moves 1 around.

Score: 1

you can store a random hash in an array 8 within your session data as well as print 7 that hash as a hidden form input value. when 6 a request comes in, if the hidden hash value 5 exists in your session array, you can delete 4 the hash from the session and process the 3 form, otherwise don't.

this should prevent 2 duplicate form submits as well as help prevent 1 csrf attacks.

Score: 0

If the problem only arises when hitting 5 a button milliseconds apart, wouldn't a 4 software debouncer work? Like saving the 3 time of a button press in a session variable 2 and not allowing any more for, say, a second? Just 1 a before-my-morning-coffee idea. Cheers.

Score: 0

What I do in order to prevent session race 9 condition in the code is after the last 8 operation that stores data in session I 7 use PHP function session_write_close() notice that if you are 6 using PHP 7 you need to disable default 5 output buffering in php.ini. If you have 4 time consuming operations it'd be better 3 to execute them after session_write_close() is 2 invoked.

I hope it'll help someone, for 1 me it saved my life :)

More Related questions