HEX
Server: LiteSpeed
System: Linux kapuas.iixcp.rumahweb.net 5.14.0-427.42.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 1 14:58:02 EDT 2024 x86_64
User: mirz4654 (1666)
PHP: 8.1.33
Disabled: system,exec,escapeshellarg,escapeshellcmd,passthru,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,shell_exec,popen,pclose,dl,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setsid,posix_setuid,posix_setpgid,ini_alter,show_source,define_syslog_variables,symlink,syslog,openlog,openlog,closelog,ocinumcols,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dll,ftp,myshellexec,socket_bind,mail,posix_getwpuid
Upload Files
File: /home/mirz4654/public_html/wp-content/plugins/vibes/includes/libraries/lock/mutex/FlockMutex.php
<?php

declare(strict_types=1);

namespace malkusch\lock\mutex;

use malkusch\lock\exception\DeadlineException;
use malkusch\lock\exception\LockAcquireException;
use malkusch\lock\exception\LockReleaseException;
use malkusch\lock\exception\TimeoutException;
use malkusch\lock\util\Loop;
use malkusch\lock\util\PcntlTimeout;

/**
 * Flock() based mutex implementation.
 *
 * @author Markus Malkusch <[email protected]>
 * @link bitcoin:1P5FAZ4QhXCuwYPnLZdk3PJsqePbu1UDDA Donations
 * @license WTFPL
 * @see flock()
 */
class FlockMutex extends LockMutex
{
    public const INFINITE_TIMEOUT = -1;

    /**
     * @internal
     */
    const STRATEGY_BLOCK = 1;

    /**
     * @internal
     */
    const STRATEGY_PCNTL = 2;

    /**
     * @internal
     */
    const STRATEGY_BUSY = 3;

    /**
     * @var resource $fileHandle The file handle.
     */
    private $fileHandle;

    /**
     * @var int
     */
    private $timeout;

    /**
     * @var int
     */
    private $strategy;

    /**
     * Sets the file handle.
     *
     * @param resource $fileHandle The file handle.
     * @param int $timeout
     */
    public function __construct($fileHandle, int $timeout = self::INFINITE_TIMEOUT)
    {
        if (!is_resource($fileHandle)) {
            throw new \InvalidArgumentException('The file handle is not a valid resource.');
        }

        $this->fileHandle = $fileHandle;
        $this->timeout = $timeout;
        $this->strategy = $this->determineLockingStrategy();
    }

    private function determineLockingStrategy()
    {
        if ($this->timeout == self::INFINITE_TIMEOUT) {
            return self::STRATEGY_BLOCK;
        }

        if (PcntlTimeout::isSupported()) {
            return self::STRATEGY_PCNTL;
        }

        return self::STRATEGY_BUSY;
    }

    /**
     * @throws LockAcquireException
     */
    private function lockBlocking(): void
    {
        if (!flock($this->fileHandle, LOCK_EX)) {
            throw new LockAcquireException('Failed to lock the file.');
        }
    }

    /**
     * @throws LockAcquireException
     * @throws TimeoutException
     */
    private function lockPcntl(): void
    {
        $timebox = new PcntlTimeout($this->timeout);

        try {
            $timebox->timeBoxed(
                function (): void {
                    $this->lockBlocking();
                }
            );
        } catch (DeadlineException $e) {
            throw TimeoutException::create($this->timeout);
        }
    }

    /**
     * @throws TimeoutException
     * @throws LockAcquireException
     */
    private function lockBusy()
    {
        $loop = new Loop($this->timeout);
        $loop->execute(function () use ($loop): void {
            if ($this->acquireNonBlockingLock()) {
                $loop->end();
            }
        });
    }

    /**
     * @throws LockAcquireException
     * @return bool
     */
    private function acquireNonBlockingLock(): bool
    {
        if (!flock($this->fileHandle, LOCK_EX|LOCK_NB, $wouldBlock)) {
            if ($wouldBlock) {
                /*
                 * Another process holds the lock.
                 */
                return false;
            }
            throw new LockAcquireException('Failed to lock the file.');
        }

        return true;
    }

    /**
     * @throws LockAcquireException
     * @throws TimeoutException
     */
    protected function lock(): void
    {
        switch ($this->strategy) {
            case self::STRATEGY_BLOCK:
                $this->lockBlocking();

                return;
            case self::STRATEGY_PCNTL:
                $this->lockPcntl();

                return;
            case self::STRATEGY_BUSY:
                $this->lockBusy();

                return;
        }

        throw new \RuntimeException("Unknown strategy '{$this->strategy}'.'");
    }

    /**
     * @throws LockReleaseException
     */
    protected function unlock(): void
    {
        if (!flock($this->fileHandle, LOCK_UN)) {
            throw new LockReleaseException('Failed to unlock the file.');
        }
    }
}