PHP flock LOCK_EX|LOCK_NB race conditions - php

After much digging around I haven't been able to identify the issue behind a race condition I'm finding on a little PHP pseudo-cron.
The code looks like this:
fh = fopen(ROOT . '.cron.lock', 'w+');
if (flock($fh, LOCK_EX|LOCK_NB)) {
//Cron logic goes here
flock($fh, LOCK_UN);
}
It should be pretty straightforward, and usually does work. The point is that every so often, this little cron executes twice (sending a duplicate email to a user), which is rather annoying.
Initially I thought I'd have to use the third $ewouldblock parameter. But this has turned out not to work, just causing the cron to execute always without regard for any other process.
Whenever I test this code in a CLI environment, it works perfectly fine. But it won't as soon as I move over to using the script inside a HTTPD (Apache) request.
http://php.net/manual/en/function.flock.php
If anyone can help, or maybe give me a pointer what the whole $ewouldblock parameter is about (since the documentation is not very straightforward about it) I would appreciate a lot.

Related

PHP light alarm clock how do I check my time is equal to a set time?

I am trying to allow my simple website to check the time, so that if the set alarm time is equal to the real time the alarm goes off.
I'm using PHP (and I am pretty sure it must be in PHP due to using LEDs and python). I know this is relatively easy thing to do in js for example.
I have the variables:
$setTime = "$hour$hour2:$minutes$minutes2";
$realTime = date("H:i");
and a if statement:
if ($realTime == $setTime) {
exec("sudo python /home/pi/lighton_1.py");
}
else{
exec("sudo python /home/pi/lightoff_1.py");
}
This all works if when I load my website the real time = the set time however if not it won't. I somehow really want to check the if statement so often somehow. I have tried loops, functions etc and haven't had much success however my coding is a bit basic at the moment. Wondering if anyone knows this solution, (could be very simple?) Need help fast please. Thank you!
You need to understand how your PHP code is triggered. When used to host a website, it is triggered, when someone requests a page. Now, what are the chances than someone will request this page when "$realTime == $setTime". Unless you host a very busy site, the chances are very small. You could have a web page run a JavaScript to continuously refresh the page. Even in this case you may want to say "$realTime > $setTime".
You could alternatively run your PHP from a scheduler like a Unix Cron job, or some kind of PHP scheduler, but then you have to say "$realTime > $setTime", because scheduler may also not run this statement at the exact moment.

How to echo a ' . ' in every 3 seconds while your application is running?

I am running my PHP in CLI.
My script might take about 3-4 mn to complete.
When looking at the CLI, all I see is this :
That doesn't help me much, I am not sure whether my application is stuck or still running. (Visually)
What is the best way to keep track of that ?
I am thinking to echo "." in every 3 seconds while my application is running.
Basically, I want to give myself some visually feedback while my script is loading/running.
If you going to suggest me to log it :
I actually do log my $response and output it to a file somewhere in my desktop, and the reason why I am asking this question, I just want to create a visually feedback - like when you playing a video game and while you waiting for something to finish loading, you will see the screen with Now loading ........ or something that is similar to that - am I right ?
Yes - I want to make something similar to that !
Why don't you just let your program write a log file whilst it's running. Like this, you can log every single move, every detail you are interested in. And watch the progress in the file and let the program do what it should do.
A great tool for this is monolog which makes it very easy to log in case of errors or success.
As I just read your comment, once again, let it log the moves...
I think you could do like control points... You could echo everytime you finalize a task... If you are doing loops you can echo every new loop if the loop is not too big.
That way you know in what point of the task you are. I think you get the idea, also you should check your vars for the expected types. That way no function should have any error.
PHP is synchronous by nature, it won't move on to the next line until the previous command has returned.
You can use it asynchronously by using threading (pthreads) or running commands in a background shell.
Update:
Since you stated in the comments: "posting about 30,000 object in 1 jSON". I'm assuming these are in a loop? Why not do something like this?
$time = time();
for {
# post object here
if (time()-$time >= 3) {
echo '.';
$time = time();
}
}
Pretty simple solution. Won't output exactly every 3 seconds, but it should be good enough for your purpose (just making sure things are progressing).
You could use register_tick_function() to have a callback executed during execution - just record how long its been since you last output anything, and send more output when that's expire.
Really though, it's better to design an application to provide feedback or logging from the outset. But it's good to know register_tick_function is available!
Rather than echo out the " . " every 3 seconds I can just do echo "." after every-line of code.
Now - I got this result - close enough to what I want anyway.

php waiting between two operation (multi-threading)

I have code structure like this
echo "First Operation";
sleep(3);
echo "Second Operation";
I want to try simulate multi-threading but I could not make, sleep function is meaningless there, but I could not find another option.
I have to agree that PHP is not built for multithread. As such the script you create will always run in one thread. There are some exceptions to that. When you call a shell command there is the possibility to fire-and-forget the command when you dont need the output. It runs parallel but you can not access the result.
PHP is designed to execute one instruction after the other.
To create something like a parallel working script, you need to take advantage of some external systems. All of those tricks are related to your actual solution you wane try to accomplish. Let me give you an example.
You could use a Message Queueing system like Rabbit MQ to work as a separation between one script and the other. Lets say script1 is permanently listening on the queue for work to do. Another script, lets say script2, is (on request) bushing a work into the queue and continuing with other stuff while the script1 is picking that up, doing something and returning the answer. When script2 is done with the other stuff it can read the result from the queu and finish whatever you want to do.
This is actually a very tricky and theoretical concept, but it might give you an idea. But without any external component like the queue, php will not work multithreaded.
I hope that is helping you!

Potentially write to same file in PHP multiple times at once?

I am using PHP's fputcsv to log votes in an application we are making. The saving part of my code roughly ressembles this:
$handle = fopen('votes.csv', 'a');
fputcsv($handle, $data);
fclose($handle);
This works flawlessly in tests. However, I have a small concern. When deployed in production, it's possible that many many users will be making a request to this script at the same time. I am curious as to how PHP will handle this.
Will I potentially have problems, and lose votes because of that? If so, what can I do to prevent it? Is the solution more complex than simply using a database? And finally, how can I test for this situation, where a lot of requests would be made at the same time? Are there things that already exist to test this sort of stuff?
Writing to a file can cause issues with concurrent users. If you instead insert into a database, you can let the database itself handle the queue. If you run out of connections, it is easily tracked and you can see the load on the db as you go.
An insert in a database will be less resource heavy than an append to a file. Having said that, you would need pretty heavy load for either to take effect - but with a database, you have the build in query queue to alleviate a good portion of the concurrent stress.
When you send a request to a database, it actually goes into a queue for processing. It only fails to be executed if there is a timeout in your PHP code (basically, PHP is told to abandon the wait for the db to respond - and you can control this via PHP and Apache settings) so you have a fantastic built-in buffer.

PHP Background Process on BSD uses 100% CPU

I have a PHP script that runs as a background process. This script simply uses fopen to read from the Twitter Streaming API. Essentially an http connection that never ends. I can't post the script unfortunately because it is proprietary. The script on Ubuntu runs normally and uses very little CPU. However on BSD the script always uses nearly a 100% CPU. The script is working just fine on both machines and is the exact same script. Can anyone think of something that might point me in the right direction to fix this? This is the first PHP script I have written to consistently run in the background.
The script is an infinite loop, it reads the data out and writes to a json file every minute. The script will write to a MySQL database whenever a reconnect happens, which is usually after days of running. The script does nothing else and is not very long. I have little experience with BSD or writing PHP scripts that run infinite loops. Thanks in advance for any suggestions, let me know if this belongs in another StackExchange. I will try to answer any questions as quickly as possible, because I realize the question is very vague.
Without seeing the script, this is very difficult to give you a definitive answer, however what you need to do is ensure that your script is waiting for data appropriately. What you should absolutely definitely not do is call stream_set_timeout($fp, 0); or stream_set_blocking($fp, 0); on your file pointer.
The basic structure of a script to do something like this that should avoid racing would be something like this:
// Open the file pointer and set blocking mode
$fp = fopen('http://www.domain.tld/somepage.file','r');
stream_set_timeout($fp, 1);
stream_set_blocking($fp, 1);
while (!feof($fp)) { // This should loop until the server closes the connection
// This line should be pretty much the first line in the loop
// It will try and fetch a line from $fp, and block for 1 second
// or until one is available. This should help avoid racing
// You can also use fread() in the same way if necessary
if (($str = fgets($fp)) === FALSE) continue;
// rest of app logic goes here
}
You can use sleep()/usleep() to avoid racing as well, but the better approach is to rely on a blocking function call to do your blocking. If it works on one OS but not on another, try setting the blocking modes/behaviour explicitly, as above.
If you can't get this to work with a call to fopen() passing a HTTP URL, it may be a problem with the HTTP wrapper implementation in PHP. To work around this, you could use fsockopen() and handle the request yourself. This is not too difficult, especially if you only need to send a single request and read a constant stream response.
It sounds to me like one of your functions is blocking briefly on Linux, but not BSD. Without seeing your script it is hard to get specific, but one thing I would suggest is to add a usleep() before the next loop iteration:
usleep(100000); //Sleep for 100ms
You don't need a long sleep... just enough so that you're not using 100% CPU.
Edit: Since you mentioned you don't have a good way to run this in the background right now, I suggest checking out this tutorial for "daemonizing" your script. Included is some handy code for doing this. It can even make a file in init.d for you.
How does the code look like that does the actual reading? Do you just hammer the socket until you get something?
One really effective way to deal with this is to use the libevent extension, but that's not for the feeble minded.

Categories