You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.4 KiB
112 lines
3.4 KiB
<?php
|
|
/***************************************************************************
|
|
* This gives a method of mutual exclusion for critical Sections within
|
|
* your script. A lock-file will be created for every critical section that
|
|
* must be secured. The file hold information about the lock and is a
|
|
* handle (name) for the lock, so that every script uses the same lock.
|
|
* The lock will be achieved by one of two ways.
|
|
*
|
|
* 1. by using semaphores if they are available within the current php
|
|
* installation.
|
|
* 2. else by using flock, which exists within every php installation.
|
|
*
|
|
* Semaphores are used in favour because flock did not work reliably in
|
|
* threaded environments. That means, if we have no semaphores and are
|
|
* in a threaded environment these functions are also not reliable.
|
|
* In doubt ask your administrator or provider.
|
|
*
|
|
* Author: Georg Steffers <georg@steffers.org
|
|
* Date: 14th Oct. 2007
|
|
***************************************************************************/
|
|
|
|
require_once LIBDIR . 'errException.php';
|
|
|
|
/**
|
|
* Try to acquire a lock to enter a critical section. If the lock is already
|
|
* acquired the function blocks until the lock id freed again. If more than
|
|
* one process waits for the lock, than it is undefined which process get
|
|
* the lock next. This depends on which process gets CPU time first. All other
|
|
* processes continue waiting.
|
|
*
|
|
* Sideeffects:
|
|
* If this function succeeds ignore_user_abort is set to TRUE so that the
|
|
* critical section might not be interruped by a user abort. This can
|
|
* but shouldn't be changed within the critical section and will be reset
|
|
* in releaseLock.
|
|
*
|
|
* Arguments:
|
|
* $lockFile <string>: Path and basename to the lockfile to use.
|
|
* $csId <string[1]>: Id of the critical section, will be part of filename.
|
|
* $msg <string>: The message to be written to the lockfile.
|
|
*
|
|
* If $msg is NULL, a default message is created from session_id and time
|
|
*
|
|
* Returns:
|
|
* Array of lock information.
|
|
* [0] Filehandle to opened lockfile.
|
|
* [1] Resource id for semaphor
|
|
* [2] the old setting of ignore_user_abort.
|
|
*/
|
|
function acquireLock ($lockFile, $csId, $msg = NULL)
|
|
{
|
|
$fName = $lockFile . $csId . '.lck';
|
|
$lock = NULL;
|
|
|
|
setErrExceptionMapping ();
|
|
|
|
$lockHandle = fopen ($fName, 'w');
|
|
|
|
// if available use semaphores for mutual exclusion because flock
|
|
// doesn't work reliably in threaded environments.
|
|
if (function_exists ('sem_get'))
|
|
{
|
|
$lock = sem_get (ftok ($fName, $csId), 1, 0644, TRUE);
|
|
|
|
$state = sem_acquire ($lock);
|
|
while ($state === FALSE)
|
|
$state = sem_acquire ($lock);
|
|
}
|
|
else
|
|
{
|
|
$state = flock ($lockHandle, LOCK_EX);
|
|
while ($state === FALSE)
|
|
$state = flock ($lockHandle, LOCK_EX);
|
|
}
|
|
|
|
// Here one could write informations in the lockfile...time, pid, etc.
|
|
if ($msg === NULL)
|
|
$msg = session_id () . '::' . time ();
|
|
fwrite ($lockHandle, $msg . "\n");
|
|
fflush ($lockHandle);
|
|
|
|
resetErrExceptionMapping ();
|
|
|
|
$userAbort = ignore_user_abort(TRUE);
|
|
return array ($lockHandle, $lock, $userAbort);
|
|
}
|
|
|
|
/**
|
|
* Release a lock previously acquired by acquireLock.
|
|
*
|
|
* Sideeffects:
|
|
* Sets ignore_user_abort to the value before acquireLock succeds.
|
|
*
|
|
* Arguments:
|
|
* $lock <array[3]>: The array returned by a successfull acquireLock call.
|
|
*/
|
|
function releaseLock ($lock)
|
|
{
|
|
setErrExceptionMapping ();
|
|
|
|
if ($lock[1] !== NULL)
|
|
sem_release ($lock[1]);
|
|
|
|
ftruncate ($lock[0], 0);
|
|
fclose ($lock[0]);
|
|
|
|
resetErrExceptionMapping ();
|
|
|
|
ignore_user_abort($lock[2]);
|
|
}
|
|
|
|
?>
|