Simultaneous AJAX and PHP Sessions

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
winklerd
Forum Newbie
Posts: 2
Joined: Fri Jul 23, 2010 4:19 pm

Simultaneous AJAX and PHP Sessions

Post by winklerd »

(cross-posted to stackoverflow.com)

I'm having a peculiar problem with making simultaneous AJAX requests that modify a PHP object stored in the session. I'm having problems with race conditions but I don't understand why they're happening... only one AJAX call can have the session open at a time, so if they keep the session open while making modifications, shouldn't each call be able to see the changes made by the others? Here's a simplified version of the flow (A and B are two sets of parameters):

1) An AJAX call is made which runs Initiate(A). This call opens the session. It updates the PHP object by adding "A - Running" to an array.
2) An AJAX call to Run(A) is made. It waits until Initiate(A) closes the session and then runs. It briefly opens the session but explicitly closes it and does not modify the object. Run(A) will take up to 60 seconds to run.
3) Another AJAX call is made which runs Initiate(B). This opens the session and modifies the object by adding "B - Running" to the array.
4) Another AJAX call is made to Run(B). It opens the session briefly but explicitly closes it.

So far, everything is great. Run(A) and Run(B) are both executing. Both "A - Running" and "B - Running" are in the object's array, stored in the session which is not open in either request. Here's where things get funny:

5) Run(A) finishes executing first and an AJAX call is made which runs Show(A). This opens the session, retrieves the object, and changes "A - Running" to "A - Complete". Funny thing is, "Running - B" is not there at all.
6) When Run(B) finishes, an AJAX call is made that executes Show(B). This opens the session and retrieves the object. It changes "B - Running" to "B - Complete". The first element in the array, however, is "A - Running".

If the session is closed and saved, when Show(A) opens it, why can't it see the changes made by Initiate(B)? And when Initiate(B) can clearly see the changes made by Initiate(A), but Show(B) can't see what Show(A) did...

Similar problems happen if Run(B) finished before Run(A).
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: Simultaneous AJAX and PHP Sessions

Post by John Cartwright »

I haven't exactly followed your logic carefully, but it sounds like you could benefit from explicitely calling session_write_close() after your session changes on long running scripts. This will force PHP to immediately write the changes to your session without the script ending.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Simultaneous AJAX and PHP Sessions

Post by Weirdan »

1. Are you using PHP's built-in file-based session handler?
2. Are you sure your session id is not changed in between the calls?
3. You could add file-based logging to see the exact sequence and values - this could shed some light on the situation:

Code: Select all

  // run(a)
  session_start();
  file_put_contents('/tmp/call-log', time() . ':run(a): ' . var_export($_SESSION, true) . PHP_EOL . PHP_EOL, FILE_APPEND);
  session_write_close();
  // do the work
winklerd
Forum Newbie
Posts: 2
Joined: Fri Jul 23, 2010 4:19 pm

Re: Simultaneous AJAX and PHP Sessions

Post by winklerd »

John: That's what we were doing which actually "caused" the problem. We need other AJAX requests to be able to run, so we did an explicit session_write_close() so it didn't hold the session open.
Weirdan: Yes we were using the built-in session handling, yes I'm sure the session name and ID are not changing.

It appears to be a bug in the framework (eyeOS) we're using. It seems to require that the session be open when it performs its cleanup or something. So I do a session_write_close() somewhere, then have to session_start() again before eyeOS does its thing.
Post Reply