Detecting early termination of HTTP connection in Symfony 1.4 - php

I'm interested in using the mark as read method for emails and in-app notifications as specified here
I'm using Symfony 1.4 and I can't find anything within sfContext or sfWebRequest that can be used to detect if the connection has been terminated. Is there anyway to do this within the Symfony framework?
Would I be able to use the PHP functions connection_status() or connection_aborted()?

In a typical PHP script, the script execution will stop at the next tickable event after the user terminates a connection.
Because of this, you shouldn't need to really do anything to get this to work (unless you have changed this setting in your php.ini) or someone has set the ignore_user_abort flag.
But, if you want to be safe, you could do the following:
<?php
// Whatever you need here
sleep(5);
if (false == connection_aborted()) {
// Mark the notification as read
}

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.

Using server-sent events and php sessions

I'm using in my project server-sent events where the JS is calling a PHP page, say eventserver.php which consists basically of an infinite loop which checks the existence of an event in a $_SESSION variable.
On my first implementation this lead my website to hung up because the eventserver took the lock on the session and did not release it until the timeout expired; however, I managed to resolve this issue by locking/unlocking the session by using session_write_lock() and
session_start() continuously in the loop.
This is actually causing a lot of PHP warnings (on Apache error.log) saying that "cannot send session cache limiter - headers already sent", "cannot send session cookies" and so on.
Posting some code here
session_start();
header('Cache-Control: no-cache');
header('Content-Type: text/event-stream');
class EventServer
{
public function WaitForEvents( $eventType )
{
// ... do stuff
while( true )
{
// lock the session to this instance
session_start();
// ...check/output the event
ob_flush();
flush();
// unlock the session
session_write_close();
sleep( 1 );
}
}
}
Why is this happening?
I am doing the same thing as the OP and ran into the same issue. Some of these answers don't understand how eventSource should work. My code is identical to yours and uses a session variable to know what view the user is on which drives what data to return in the event of a server trigger. It's part of a realtime collaboration app.
I simply prepended an # to the session_start() to suppress the warnings in the log. Not really a fix, but it keeps the log from filling up.
Alternatively, not sure how well it would work for your application, but you could use ajax to write the session variable you are monitoring to the database, then your eventSource script can monitor for a change in the DB instead of having to start sessions.
This is not a good idea. HTTP is a request-response protocol so if you want server-client communication to be bi-directional you will need to look into websockets or something similar. There are also things like "long polling" and "heart beating"
If you want an event loop try something like servlets in apache tomcat.
You will grapple for hours with issues because of your design.
Also check out ajax if you just want to shoot messages from javascript to PHP.
Make sure you know an overview of the tech stack you are working with :)
You don't need an infinite loop with SSE. The EventSource keeps an open connection to the server and any update on the server side data will be read by the client.
Check out basic usage of SSE here
It's probably because you start the session twice in your code. Don't restart the session at the beginning of the loop, but after the sleep().

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.

PHP - set time limit effectively

I have a simple script that makes redirection to mobile version of a website if it finds that user is browsing on mobile phone. It uses Tera-WURFL webservice to acomplish that and it will be placed on other hosting than Tera-WURFL itself. I want to protect it, in case of Tera-WURFL hosting downtime. In other words, if my script takes more than a second to run, then stop executing it and just redirect to regular website. How to do it effectively (so that the CPU would not be overly burdened by the script)?
EDIT: It looks that TeraWurflRemoteClient class have a timeout property. Read below. Now I need to find how to include it in my script, so that it would redirect to regular website in case of this timeout.
Here is the script:
// Instantiate a new TeraWurflRemoteClient object
$wurflObj = new TeraWurflRemoteClient('http://my-Tera-WURFL-install.pl/webservicep.php');
// Define which capabilities you want to test for. Full list: http://wurfl.sourceforge.net/help_doc.php#product_info
$capabilities = array("product_info");
// Define the response format (XML or JSON)
$data_format = TeraWurflRemoteClient::$FORMAT_JSON;
// Call the remote service (the first parameter is the User Agent - leave it as null to let TeraWurflRemoteClient find the user agent from the server global variable)
$wurflObj->getCapabilitiesFromAgent(null, $capabilities, $data_format);
// Use the results to serve the appropriate interface
if ($wurflObj->getDeviceCapability("is_tablet") || !$wurflObj->getDeviceCapability("is_wireless_device") || $_GET["ver"]=="desktop") {
header('Location: http://website.pl/'); //default index file
} else {
header('Location: http://m.website.pl/'); //where to go
}
?>
And here is source of TeraWurflRemoteClient.php that is being included. It has optional timeout argument as mentioned in documentation:
// The timeout in seconds to wait for the server to respond before giving up
$timeout = 1;
TeraWurflRemoteClient class have a timeout property. And it is 1 second by default, as I see in documentation.
So, this script won't be executed longer than a second.
Try achieving this by setting a very short timeout on the HTTP request to TeraWurfl inside their class, so that if the response doesn't come back in like 2-3 secs, consider the check to be false and show the full website.
The place to look for setting a shorter timeout might vary depending on the transport you use to make your HTTP request. Like in Curl you can set the timeout for the HTTP request.
After this do reset your HTTP request timeout back to what it was so that you don't affect any other code.
Also I found this while researching on it, you might want to give it a read, though I would say stay away from forking unless you are very well aware of how things work.
And just now Adelf posted that TeraWurflRemoteClient class has a timeout of 1 sec by default, so that solves your problem but I will post my answer anyway.

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

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.

Categories