PHP, Pause script execution until an event is signaled by another running script?

4.4k views Asked by At

I want one PHP script to wait for an event sent during the execution of another script.

User A and User B are both visitors of my website. When user A visits index.php, the page begins execution but does not return until User B also visit index.php. (The page is only displayed when both user are connected to the web server, ex.: like two guards opening a safe by turning the key at the same time.)

One way to make this happen is for index.php to pause its execution until a notification is received caused by the other user's visit to index.php.

To do this, I have looked at

  1. libevent; But it does not seem to allow "ID" or "strings" to be sent during signaling.
  2. Event_Dispatcher from pear; But it does not work "between" scripts.
  3. PHP shared memory functions; But does not appear to be able to wait until the memory is changed.
4

There are 4 answers

1
bensiu On

you are looking for daemon, there some info how to create this:

http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/

3
Paul Calabro On

You probably wouldn't want the PHP script to pause completely. The user would kinda just sit there thinking the page froze. Instead, I would use AJAX to save the state of USER-A in a datbase and then use AJAX to again check if USER-B has had their state saved as well. The ideas is to have AJAX silently checking the status of USER-B in the background. When it does detect a login, have your callback function do stuff to the page!

3
cwallenpoole On

What about using sleep and a db?

Client 1 logs in, PHP inserts a "waiting entry" and then polls the db at a set interval (maybe using time_nanosleep) for something which has marked it "complete".
Client 2 logs in, PHP updates the "waiting entry" to set it to "complete".
Client 1, seeing that the process is complete, goes on its merry way.

If you don't have a database, this could be done with a simple temp file.

0
Matt Weeks On

In the code for your "waiting" request (User A), create a new listening socket (http://php.net/manual/en/sockets.examples.php) bound to a localhost address and port that won't conflict with anything else (for example, 127.12.34.56 port 7890) then wait for a connection by calling socket_accept. If there is already a request waiting in that state, this will fail otherwise it will wait there for a connection.

In your "signaling" request (User B), create a new socket, and connect to your listening socket. The PHP handler waiting for User A's request will immediately return from the socket_accept call it was blocked in and you can continue. If you need to pass any messages between the two, you can simply read and write the messages to and from the sockets.

This is a very common task to perform for applications like chat rooms and notification pages that display server-sent events. This approach has a few advantages over a polling approach that keeps calling sleep and checking a DB or file in a loop (or makes many requests back to the server in a loop from the JavaScript side):

-It does not create unnecessary HTTP requests or DB queries or CPU loops that consume resources and network traffic

-It acts immediately when the trigger event happens without any delay

-It does not depend on a DB or file

The main disadvantage is that your PHP must have permissions to open sockets and connect to them, which is often not the case in shared hosting environments.

For an example, see https://gist.github.com/root9b/e1f0b82769296b06c079e53c7362bb94