5

Let's say we need some lock-script that we make sure two scripts are never running at same time:

if(file_get_contents('test.txt')) { // this is always empty...
   die("Another script is running in background!");
}
file_put_contents('test.txt', 'busy!');
sleep(10); // heavy work here
file_put_contents('test.txt', '');

it still allows me to run two scripts at same time. It looks like result of file_get_contents() are cached?

How to fix it? I want to use files, not DB.


Edit: I already managed to do the lock-script using flock() (thanks to Levi Morrison)

Anyway I am still curious why file_get_contents works in so unexpected behaviour?

Peter
  • 16,453
  • 8
  • 51
  • 77
  • 3
    See [flock](http://php.net/manual/en/function.flock.php). – Levi Morrison Dec 19 '12 at 16:18
  • There should not be any caching. I'm just curious, what happens when you manually write something into the file and run your script? – Ranty Dec 19 '12 at 16:20
  • @LeviMorrison looks good, but what about `file_get_contents()` ? – Peter Dec 19 '12 at 16:20
  • @Ranty it works fine. Script exits at line 2. – Peter Dec 19 '12 at 16:21
  • 1
    @EXQStudio You don't need to use `file_get_contents()` (or even write any actual data to the file), just have all scripts `fopen()` the file in write mode and attempt to `LOCK_EX` it. All scripts will block at the `flock()` call until they are able to acquire the exclusive lock, so you are guaranteed that only one of them will be able to run at once. Just make sure you remember to `LOCK_UN` at the end of the script! – DaveRandom Dec 19 '12 at 16:24
  • @DaveRandom yes it works nice, but still - why `file_get_contents` doesn't work? – Peter Dec 19 '12 at 16:26
  • Possible duplicate: http://stackoverflow.com/questions/5526209/does-phps-file-get-contents-cache-a-301-status-code . – Tomasz Kowalczyk Dec 19 '12 at 16:28
  • @EXQStudio The only reason I can see for this happening is that whenever you run the script, the file really is empty. Without seeing exactly what you are doing/how you are running it, I can't really guess why that would be. – DaveRandom Dec 19 '12 at 16:29
  • @DaveRandom Just copy example script and try it by yourself... You may change sleep to 30 seconds so you gonna have plenty of time to check file contents.. – Peter Dec 19 '12 at 16:32
  • Let me guess, you are running your script from browser twice and second one also "is loading" long time? – Ranty Dec 19 '12 at 16:47
  • I could reproduce it once.. Then I created the test.txt again. From now on in works. Odd behaviour!! Does it work on your side after reacreating the test.txt? (Don't know what should the reason for that) Btw,I am using two Gnome Terminals for testing. – hek2mgl Dec 19 '12 at 17:04

1 Answers1

2

I was able to reproduce it and figure the problem. At first it looked the way you described: I requested the script in browser and while it was running I checked file contents - it was busy!. Then I run second script and in browser it was also loading, same as first one. I thought it's also running, but it was not.

It's pretty easy to figure, if instead of busy! you add something random, like:

file_put_contents('test.txt', 'busy washing ' . (mt_rand(1, 999) * 99999) . ' dishes');

Run the same two scripts the same way and monitor file contents. At first, it will be what first script wrote. Say busy washing 1 dishes. Then you will see the content change to what second script writes, the number will be different.

Basically, what happens is second script waits while first one finishes and only then starts. Funny enough, by finishing, first script clears the file, which lets second script run normally, but it looks in browser like they are both working at the same time. In fact, second script runs twice as much time, as the first one.

I've encountered that behaviour when doing heavy asynchronous requests via AJAX and requesting same website page in another browser tab. Until the script finishes I couldn't load the tab.

So long story short, there's no issue! If you queue that scripts via cron they will be run separately and second one will finish by finding that the file is not empty.

Ranty
  • 3,333
  • 3
  • 22
  • 24
  • And if you generate the same number two times in a row? – Levi Morrison Dec 19 '12 at 21:37
  • @LeviMorrison The number is there to demonstrate, that the problem does not exist. It has nothing to do with locking file, especially in the context of `if (file_get_contents('test.txt')) {}` – Ranty Dec 19 '12 at 21:55
  • @Ranty yes that's it. thru console everything is OK – Peter Dec 20 '12 at 09:04
  • @Ranty funny thing is when I use `flock` or DB problems doesn't exists :) issue only on WAMP, using apache everything is ok (even if I use browser) - so i believe it's server config issue, anyway thanks again for help – Peter Dec 20 '12 at 20:13
  • @EXQStudio with `flock` second script doesn't wait even in browser? – Ranty Dec 20 '12 at 20:28