Connection-related functions

int ignore_user_abort ( [bool setting])

void register_shutdown_function ( callback function)

int connection_status ( )

For the most part, your PHP scripts will produce output destined for a client somewhere, usually a web browser. But what happens if that web browser is closed halfway through your script's execution - do you finish processing and hope for the best? Furthermore, how you can always be sure a certain clean up function will be called when your script ends? The answer involves two functions, which are ignore_user_abort() and register_shutdown_function(), which allow you to carry on processing after the user has cancelled their request and you to specify the name of a function to use when the script ends, respectively.

Passing true to ignore_user_abort() as its only parameter will instruct PHP that the script is not to be terminated even if your end-user closes their browser, has navigated away to another site, or has clicked Stop. This is useful if you have some important processing to do and you do not want to stop it even if your users click cancel, such as running a payment through on a credit card. You can of course also pass false to ignore_user_abort(), thereby making PHP exit when the user closes the connection.

For handling shutdown tasks, register_shutdown_function() is perfect, as it allows you to register with PHP a function to be run when script execution ends. Take a look at this example:

<?php
    function say_goodbye() {
        echo "Goodbye!\n";
    }

    register_shutdown_function("say_goodbye");
    echo "Hello!\n";
?>

Save that code and try it out - you should get the following in output:

Hello!
Goodbye!

As you can see, say_goodbye() is called when the script ends, as planned. You can call register_shutdown_function() several times passing in different functions, and PHP will call all of the functions in the order you registered them when the script ends. If any of your shutdown functions call "exit", the script will terminate without running the rest of the functions.

One very helpful use for shutdown functions is to handle unexpected script termination - i.e. script timeout. If your script times out, you have just lost control over whatever you were doing, so you either need to back up and undo whatever you have just done, or you need to clean up and terminate cleanly. Either way, shutdown functions are perfect: register a clean up function near the start of the script, and, when script timeout happens, the clean up function will automatically run.

For example, the following script will print out "Sleeping...Goodbye!":

<?php
    function say_goodbye() {
        print "Goodbye!\n";
    }

    register_shutdown_function("say_goodbye");
    set_time_limit(1);
    print "Sleeping...\n";
    sleep(2);
    print "Done!\n";
?>

The "Done!" print line will never be executed, because the time limit is set to 1, and the sleep() function is called with 2 as its parameter, so the script will sleep for 2 seconds. As a result, "Sleeping..." gets printed, followed probably by a warning about the script going over its time limit, then the shutdown function gets called.

Of course, the problem with this thinking is that shutdown functions execute irrespective of there having been a timeout or not, therefore it is not wise to set a cleanup function as a shutdown function - it will always execute! However, PHP comes to the rescue with the connection_status() function, which takes no parameters and returns 0 if the connection is live and execution is still taking place, 1 if the connection is aborted (connection_timeout() will also return true), 2 if the connection has been aborted (connection_aborted() will also return true), and 3 if the connection has been aborted and subsequently timed out.

The last situation is only possible if ignore_user_abort(true) has been used, and the script subsequently timed out. Note that the values 0, 1, 2, and 3 evaluate to the constants CONNECTION_NORMAL, CONNECTION_ABORTED, CONNECTION_TIMEOUT, and CONNECTION_ABORTED | CONNECTION_TIMEOUT (a bit-wise OR of the previous two).

So, with this new function in mind, here is our script rewritten to take notice of whether shutdown occurred because the script finished or because script timeout was reached:

<?php
    function say_goodbye() {
        if (connection_status() == CONNECTION_TIMEOUT) {
            print "Script timeout!\n";
        } else {
            print "Goodbye!\n";
        }
    }

    register_shutdown_function("say_goodbye");
    set_time_limit(1);
    print "Sleeping...\n";
    sleep(2);
    print "Done!\n";
?>

This time, although "Done!" will still not get printed out, the script is at least able to detect a simple script timeout.

 

Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Altering the execution environment >>

Previous chapter: Executing external programs

Jump to:

 

Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.