How to determine that a PHP script is in termination phase? - php

Is there any function / global variable in PHP that returns the current state of the script (something like runnning, terminating)?
Or is the only way to set this state by making use of register_shutdown_function()?
That function looks inflexible to me as an already registered shutdown functions can be overriden with it. And the shutdown function gets executed when a user aborts the connection, which is not what I'm looking for explicitly and I don't want to introduce too many constraints.
Are there any alternatives to register_shutdown_function() available? Or if not, how to deal with the shortcomings of that function?
UPDATE
Just to clarify: I'm not looking for connection state (e.g. connection_aborted()) but for the run state of the PHP script (running, terminating). Functions to find out more about the connection state I already know of, but how about the current state of the script? Has the script already been terminated and are objects (going to be) destroyed because of that?
UPDATE2
To clarify even more, I'm still not looking for connection state but for something comparable regarding the run-state. It should work in CLI as well which does not have any connection state as there is no TCP connection related to executing the code - to better illustrate what I'm looking for.

After reading a larger part of the PHP sourcecode I came to the conclusion that even if such state(s) exist on the level of experience, they do not really exist within the interpreter in form of a flag or variable.
The code about throwing Exceptions for example decides on various variables if that is possible or not.
The answer to the question is no therefore.
The best workaround I could find so far is to have a global variable for this which is set in a registered shutdown function. But a flag from PHP seems to be not really available.
<?php
register_shutdown_function(function() {$GLOBALS['shutdown_flag']=1;});
class Test {
public function __destruct() {
isset($GLOBALS['shutdown_flag'])
&& var_dump($GLOBALS['shutdown_flag'])
;
}
}
$test = new Test;
#EOF; Script ends here.

You are looking for:
Connection_aborted();
http://it.php.net/manual/en/function.connection-aborted.php
or
Connection_status();
http://it.php.net/manual/en/function.connection-status.php
Addendum
There can't be any Terminated status, because if it's terminated you can't check its status lol

I have never made (practical) use of it myself yet, but you might be able to make use of:
http://www.php.net/manual/en/function.register-tick-function.php
Using this means you can write a file or update a db or something while script is running... i.e. write a record session/some id and a timestamp id to a file or something and check for time between execution perhaps, you could say if it's not been updated in X seconds it's still running.
But as stated PHP is stateless so it's not a notion that PHP will be aware of.
Failing this, you could set a DB field in some way when a script starts/just before it 'ends', but would place a lot of overhead really.

Is there any function / global
variable in PHP that returns the
current state of the script (something
like runnning, terminating)?
No, PHP is stateless.

Related

Use PHP semaphore in the same script [duplicate]

How to make functions in PHP synchronized so that same function won't be executed concurrently ? 2nd user must wait till 1st user is done with the function. Then 2nd user can execute the function.
Thanks
This basically comes down to setting a flag somewhere that the function is locked and cannot be executed until the first caller returns from that function.
This can be done in a number of ways:
use a lock file (first function locks a file name "f.lok", second function checks if the lock file exists and executes or doesn't based on that evaluation)
set a flag in the database (not recomended)
use semaphores as #JvdBerg suggested (the fastest)
When coding concurrent application always beware of race conditions and deadlocks!
UPDATE
using semaphores (not tested):
<?php
define('SEM_KEY', 1000);
function noconcurrency() {
$semRes = sem_get(SEM_KEY, 1, 0666, 0); // get the resource for the semaphore
if(sem_acquire($semRes)) { // try to acquire the semaphore. this function will block until the sem will be available
// do the work
sem_release($semRes); // release the semaphore so other process can use it
}
}
PHP needs to be compiled with sysvsem support in order to use sem_* functions
Here's a more in depth tutorial for using semaphores in PHP:
http://www.re-cycledair.com/php-dark-arts-semaphores
You are looking for a Semaphore
Bear in mind that using a semaphore (or any other blocking mechanism) can have serious peformance issues, as the requests can not be handled while the semaphore is up.
off the top of my head:
function checks if a database field called isFunctionRunning is equal 1. if not start executing
you update the database field called isFunctionRunning to 1
function does magic here
you update the database field called isFunctionRunning to 0
but somehow i think what you are trying to do is "wrong" and can be achieved in another way. could help if you said more details
edit: wasn't aware of php semaphores, the answer above will be way faster.
You can use the "flock" (file locking) function with the "LOCK_EX" (exclusive lock) flag to create a custom "synchronized" function that accepts a handler to be synchronized.
You may may found the code here.
I hope this helps.

Synchronized functions using PHP

How to make functions in PHP synchronized so that same function won't be executed concurrently ? 2nd user must wait till 1st user is done with the function. Then 2nd user can execute the function.
Thanks
This basically comes down to setting a flag somewhere that the function is locked and cannot be executed until the first caller returns from that function.
This can be done in a number of ways:
use a lock file (first function locks a file name "f.lok", second function checks if the lock file exists and executes or doesn't based on that evaluation)
set a flag in the database (not recomended)
use semaphores as #JvdBerg suggested (the fastest)
When coding concurrent application always beware of race conditions and deadlocks!
UPDATE
using semaphores (not tested):
<?php
define('SEM_KEY', 1000);
function noconcurrency() {
$semRes = sem_get(SEM_KEY, 1, 0666, 0); // get the resource for the semaphore
if(sem_acquire($semRes)) { // try to acquire the semaphore. this function will block until the sem will be available
// do the work
sem_release($semRes); // release the semaphore so other process can use it
}
}
PHP needs to be compiled with sysvsem support in order to use sem_* functions
Here's a more in depth tutorial for using semaphores in PHP:
http://www.re-cycledair.com/php-dark-arts-semaphores
You are looking for a Semaphore
Bear in mind that using a semaphore (or any other blocking mechanism) can have serious peformance issues, as the requests can not be handled while the semaphore is up.
off the top of my head:
function checks if a database field called isFunctionRunning is equal 1. if not start executing
you update the database field called isFunctionRunning to 1
function does magic here
you update the database field called isFunctionRunning to 0
but somehow i think what you are trying to do is "wrong" and can be achieved in another way. could help if you said more details
edit: wasn't aware of php semaphores, the answer above will be way faster.
You can use the "flock" (file locking) function with the "LOCK_EX" (exclusive lock) flag to create a custom "synchronized" function that accepts a handler to be synchronized.
You may may found the code here.
I hope this helps.

How atomic are lockfiles in PHP?

I have a PHP page that should be accessible only by one user at a time. It's a kind of "poor man's cron": A "Javascript" file, that is requested in the background. At the moment I'm thinking of creating a lock file like this:
if(file_exists($lockfile) && filemtime($lockfile) + EXPIRES_AFTER > time() ) {
die("// Page is locked.");
}
touch($lockfile);
// do stuff
unlink($lockfile);
echo "// Cron stuff was run";
But I'm not sure if there could be a very short window of opportunity between the file_exists and the touch call where another page request could check for the file existence and see that it isn't there. We're probably talking microseconds here so I would like top know at which amount of requests I really need to start worrying.
If you want to do this really precisely, then use a different approach, because there IS some time between the check and the lock.
Two possible implementations:
Use flock:
https://secure.php.net/manual/en/function.flock.php
Use something like STM:
E.g. open the lockfile for append, write something into it, close the handle. Then read the file back, and if it only has what you wrote into it then you have acquired the lock.
Other than that, your original code would probably not cause any problems.
There is no atomicity in the code you wrote, so yes, there is a race condition.
Your code has a race condition. Instead, dio_open the file with O_EXCL. This will fail if the file already exists. Unlink it when you're done.
The only thing to watch out for is if the system or the script crashes while the file exists, the script will never run again. If you are worried about this, check the age of the file (if you fail to create it) and if it's older than the longest the script could ever take, unlink it.
Using flock is another option.

Most efficient way of writing a (To File) logger in PHP?

Hopefully someone here can help me out - basically I have a logging class that I'm updating (Made it ages ago), and I want to make sure it logs messages under 98-99% of circumstances. However right now it doesn't handle exit()s, it basically just writes to a file (Opening, writing, and closing) every time a message/error is sent to the logger.
What would be the best way to handle exit()s, and be efficient in terms of disk writes? Right now I'm looking at __destruct in the logger class (With fopen, fwrite, and fclose being called in it), however I'm not quite sure if this is safe, or efficient.
Edit: What about set_error_handler()? I remember reading years ago that this was very slow and not very good for custom errors/messages (Like SQL issues)
If you wish to log something when your script ends, you should take a look at PHP's register_shutdown_function():
function shutdown()
{
// .. log code here.
}
register_shutdown_function('shutdown');
You should avoid using the __destruct() method as there is no guarantee that it will be called when you expect it to be called.
You could also take a look at PHP's built in error_log() method to write the contents to the actual PHP error log file (this is possibly more reliable than writing your own logger).
References:
http://php.net/manual/en/function.register-shutdown-function.php
http://php.net/manual/en/function.error-log.php
I always use some global function, e.g.
function BeforeExit () {
//do stuff like logging
exit;
}

php exec() error

I'm having a little problem with the following:
When I execute this line:
echo exec(createDir($somevariable));
I get this error:
Warning: exec() [function.exec]: Cannot execute a blank command in /home/mydir/myfile.inc.php on line 32
Any ideas.
Thanks.
exec() expects a string argument, which it would pass on to your operating system to be executed. In other words, this is a portal to the server's command line.
I'm not sure what function createDir() is, but unless it's returning a valid command line string, it's probably failing because of that.
In Linux, you might want to do something like
exec('/usr/bin/mkdir '.$path);
...on the other hand, you should abstain from using exec() at all costs. What you can do here, instead, is take a look at mkdir()
With exec you can execute system calls like if you were using the command line. It hasn't to do anything with executing PHP functions.
To create a directory you could do the following:
exec( 'mkdir [NAME OF DIRECTORY]' );
I'd guess that your createDir() function doesn't return anything. Might also be worth checking that $somevariable is also set to something sensible
You're misunderstanding the purpose of exec(). If all you want to do is create a directory then you should use mkdir().
I think I've derived from other posts and comments what it is you actually want to do:
I think createDir() is a PHP function you've written yourself. It does more than just make a directory - it populates it, and that might take some time.
For some reason you believe that the next command gets run before createDir() has finished working, and you thought that by invoking createDir() using exec() you could avoid this.
Tell me in a comment if this is way out, and I'll delete this answer.
It's seems unlikely that createDir() really does keep working after it's returned (if it does, then we call that 'asynchronous'). It would require the programmer to go out of their way to make it asynchronous. So check that assumption.
Even so, exec() is not for invoking PHP functions. It is for invoking shell commands (the kind of thing you type in at a command prompt). As many of us have observed, it is to be avoided unless you're very careful - the risk being that you allow a user to execute arbitrary shell commands.
If you really do have to wait for an asynchronous function to complete, there are a couple of ways this can be done.
The first way requires that the asynchronous function has been written in an amenable manner. Some APIs let you start an asynchronous job, which will give you a 'handle', then do some other stuff, then get the return status from the handle. Something like:
handle = doThreadedJob(myParam);
# do other stuff
results = getResults(handle);
getResults would wait until the job finished.
The second way isn't as good, and can be used when the API is less helpful. Unfortunately, it's a matter of finding some clue that the job is finished, and polling until it is.
while( checkJobIsDone() == false ) {
sleep(some time interval);
}
I'm guessing createDir() doesn't have a return value.
Try exec("mkdir $somevariable");

Categories