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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: agustin dot moyano at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 18:01:29 2024 UTC