| Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/repo/includes/PidLock.php |
<?php
namespace Wikibase\Repo;
/**
* Utility class for process identifier (PID) locking.
*
* @since 0.5
*
* @license GPL-2.0+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author Tobias Gritschacher
* @author Jens Ohlig < jens.ohlig@wikimedia.de >
* @author John Erling Blad < jeblad@gmail.com >
* @author Marius Hoch < hoo@online.de >
* @author Thiemo Mättig
*/
class PidLock {
/**
* @var string
*/
private $module;
/**
* @var string|null
*/
private $wikiId;
/**
* @param string $module used as a basis for the file name.
* @param string|null $wikiId the wiki's id, used for per-wiki file names. Defaults to wfWikiID().
*/
public function __construct( $module, $wikiId = null ) {
$this->module = $module;
$this->wikiId = $wikiId;
}
/**
* Check the given process identifier to see if it is alive.
*
* @param int $pid the process identifier to check
*
* @return bool true if the process exist
*/
private function isAlive( $pid ) {
// Are we anything but Windows, i.e. some kind of Unix?
if ( strtoupper( substr( PHP_OS, 0, 3 ) ) !== 'WIN' ) {
return !!posix_getsid( $pid );
}
$processes = explode( "\n", shell_exec( 'tasklist.exe' ) );
if ( is_array( $processes ) ) {
foreach ( $processes as $process ) {
if ( strpos( 'Image Name', $process ) === 0 || strpos( '===', $process ) === 0 ) {
continue;
}
if ( preg_match( '/\d+/', $process, $matches )
&& (int)$pid === (int)$matches[0]
) {
return true;
}
}
}
return false;
}
/**
* Tries to allocate a process identifier based lock for the process, to avoid running more than
* one instance.
*
* Note that this method creates the file if necessary.
*
* @since 0.5
*
* @param bool $force make the function skip the test and always grab the lock
*
* @return bool true if we got the lock, i.e. if no instance is already running,
* or $force was set.
*/
public function getLock( $force = false ) {
$file = $this->getStateFile();
if ( $force !== true ) {
// check if the process still exist and is alive
// XXX: there's a race condition here.
if ( file_exists( $file ) ) {
$pid = (int)file_get_contents( $file );
if ( $this->isAlive( $pid ) === true ) {
return false;
}
}
}
file_put_contents( $file, getmypid() );
return true;
}
/**
* Remove the process identifier lock. Assumes that we hold it.
*
* @return bool Success
*/
public function removeLock() {
return unlink( $this->getStateFile() );
}
/**
* Generate a name and path for a file to store some kind of state in.
*
* @return string File path
*/
private function getStateFile() {
$fileName = preg_replace( '/[^a-z\d]+/i', '', $this->module ) . '_'
. preg_replace( '/[^a-z\d]+/i', '', $this->wikiId ?: wfWikiID() ) . '.pid';
// Directory /var/run/ with system specific separators
$dir = DIRECTORY_SEPARATOR . 'var' . DIRECTORY_SEPARATOR . 'run' . DIRECTORY_SEPARATOR;
$file = $dir . $fileName;
// Let's see if we can write to the file in /var/run
if ( !is_writable( $file ) && ( !is_dir( $dir ) || !is_writable( $dir ) ) ) {
// else use the temporary directory
$file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $fileName;
}
return $file;
}
}