php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62928 sem_acquire won't lock on forked environment
Submitted: 2012-08-24 20:14 UTC Modified: -
From: agustin dot moyano at gmail dot com Assigned:
Status: Open Package: Semaphore related
PHP Version: 5.4.6 OS: openSUSE 12.1 (x86_64)
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2012-08-24 20:14 UTC] agustin dot moyano at gmail dot com
Description:
------------
The actual php version is 

# php --version
PHP 5.5.0-dev (cli) (built: Aug 24 2012 16:34:36) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies

php was configured with:
./configure --enable-sysvsem --enable-sysvshm --enable-pcntl

sem_acquire won't lock when a forked process acquires the semaphore. This 
behaviour is the same whether sem_get is called in every process or before the 
first pcntl_fork. 

It would seem sem_acquire treats forked processes as if they where the same 
process as the father, even if the got different pid.

I also tryed this bug with 

$ php --version
PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch (cli) (built: Jun 13 2012 17:19:58) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

in 

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.1 LTS
Release:        12.04
Codename:       precise

whith exactly the same results. Thanks.

Test script:
---------------
<?php
$pid = pcntl_fork();
if ($pid == -1) {
	die("could not fork 1");
} else if ($pid) {
	$pid = pcntl_fork();
	if ($pid == -1) {
		die("could not fork 2");
	} else if($pid) {
		$sem = sem_get('1234');
		echo "father try acquire $sem\n";
		$time = microtime();
		sem_acquire($sem);
		echo "father acquired in ".($time-microtime())."\n";
	} else {
		$sem = sem_get('1234');
		echo "son 2 try acquire $sem\n";
		$time=microtime();
		sem_acquire($sem);
		echo "son 2 acquired in ".($time-microtime())."\n";
	}
} else {
	$sem = sem_get('1234');
	echo "son 1 try acquire $sem\n";
	$time=microtime();
	sem_acquire($sem);
	echo "son 1 acquired in ".($time-microtime())."\n";
}
?>

Expected result:
----------------
storage-tests:~ # php prueba.php 
father try acquire Resource id #4                                                                                            
father acquired in -4.6999999999964E-5                                                                                       
son 2 try acquire Resource id #4                                                                                             
son 1 try acquire Resource id #4

Actual result:
--------------
storage-tests:~ # php prueba.php 
father try acquire Resource id #4                                                                                            
father acquired in -4.6999999999964E-5                                                                                       
son 2 try acquire Resource id #4                                                                                             
son 1 try acquire Resource id #4                                                                                             
son 2 acquired in -0.00010599999999999                                                                                       
son 1 acquired in -0.00010499999999997

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-03-20 11:18 UTC] peter dot bridgman at dexdyne dot com
I don't believe this to be a bug as described. What is happening here is due to the [, int $auto_release = 1 
] part of the sem_get function signature (see http://www.php.net/manual/en/function.sem-get.php). When each 
process terminates, as auto_release is set to 1, the semaphore is automatically released, thus allowing one 
other (blocking) call to sem_acquire to succeed. That successful call then results in the process 
terminating, 'auto_release'-ing the semaphore and allowing the next sem_acquire to succeed.

Replacing the sem_get calls in the example with something like "$sem = sem_get('1234', 1, 0666, 0);" SHOULD 
results in the behaviour you desire. HOWEVER, Bug #52701 means that this doesn't work either; in fact, there 
is no working way to prevent a SysV semaphore from automatically being released upon process termination at 
the moment.

Nonetheless, fundamentally the semaphores ARE working; this can be verified with the addition of the 
following lines after each of your echo "x acquired in..." lines.

sleep(1);
die("Process dead.".PHP_EOL);

Tested with:

PHP 5.3.3 (cli) (built: Feb 22 2013 02:51:11)
PHP 5.3.3-7+squeeze14 with Suhosin-Patch (cli) (built: Aug  6 2012 14:18:06)
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Jun 25 22:01:26 2019 UTC