Skip to content

Commit

Permalink
Prevent double unlocks when a lock guard is used
Browse files Browse the repository at this point in the history
  • Loading branch information
zhgzhg committed Jan 2, 2024
1 parent 2b1930b commit e98c7b4
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions GPhpThread.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* SOFTWARE.
*
* @author zhgzhg @ github.com
* @version 1.0.5
* @version 1.0.6
* @copyright zhgzhg, 2024
*/

Expand Down Expand Up @@ -1509,9 +1509,11 @@ public static final function __set_state($name) {


/**
* A wrapper providing RAII mechanism for locking and unlocking
* purposes of a critical section objects and a similar ones.
* A wrapper providing RAII mechanism for locking and unlocking purposes
* of critical section objects or similar, which also accounts for the
* thread from which it has been created.
* @see \GPhpThreadCriticalSection
* @see \GPhpThreadNotCloneableContainer
* @throws \GPhpThreadException When improperly passed/configured a critical section or clone attempts are made.
* @api
*/
Expand All @@ -1523,6 +1525,8 @@ class GPhpThreadLockGuard implements \Serializable // {{{
private $unlockMethod = 'unlock';
/** @var string $unlockMethodsParams The parameters passed to the critical section's unlock method during an unlock. */
private $unlockMethodsParams = array();
/** @var \GPhpThreadNotClonableContainer $unlockOnceProtector Used to prevent unlocking of the same critical section from multiple heavy threads. */
private $unlockOnceProtector = NULL;

/**
* Constructor. Immediately locks the passed critical section.
Expand All @@ -1549,6 +1553,8 @@ public final function __construct(&$criticalSectionObj, $lockMethod = 'lock', ar

$this->unlockMethod = $unlockMethod;
$this->unlockMethodsParams = $unlockMethodsParams;
$this->unlockOnceProtector = new \GPhpThreadNotCloneableContainer();
\GPhpThread::isInGPhpThread($this->unlockOnceProtector);

call_user_func_array(array($this->criticalSectionObj, $lockMethod), $lockMethodParams);
}
Expand All @@ -1560,7 +1566,9 @@ public final function __destruct() {
if (!is_object($this->criticalSectionObj)) {
throw new \GPhpThreadException('Uninitialized &$criticalSectionObj attempted to be unlocked via GPhpThreadLockGuard!');
}
call_user_func_array(array($this->criticalSectionObj, $this->unlockMethod), $this->unlockMethodsParams);
if (!$this->unlockOnceProtector->export()) {
call_user_func_array(array($this->criticalSectionObj, $this->unlockMethod), $this->unlockMethodsParams);
}
}

/** @internal */
Expand Down

0 comments on commit e98c7b4

Please sign in to comment.