php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42064 exec() deadlocks if another thread is waiting for a file lock
Submitted: 2007-07-22 02:50 UTC Modified: 2007-10-22 11:31 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: tstarling at wikimedia dot org Assigned:
Status: Not a bug Package: Filesystem function related
PHP Version: 5.2.3 OS: win32 only
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: tstarling at wikimedia dot org
New email:
PHP Version: OS:

 

 [2007-07-22 02:50 UTC] tstarling at wikimedia dot org
Description:
------------
This appears to be Win32 specific.

The shell execution functions, exec(), passthru(), etc., deadlock if another thread in the same server is waiting for a file lock.

The most common type of file lock is a lock on a session file, that's where I saw this first. But I could reproduce it with flock() instead of session_start().

The typical way for this to manifest itself is if a browser sends two requests to PHP concurrently, with the same session ID. One request runs first, the other one blocks waiting for a lock on the session file. Then if the running request tries to run exec(), it deadlocks and both threads wait forever. 

Tested with both Apache 2.0.54 (mpm_winnt) and 1.3.28. I also had a colleague confirm it on an independent system. 

Reproduce code:
---------------
<?php
if ( isset( $_REQUEST['f'] ) ) {
	$f = fopen( 'blah', 'w' );
	flock( $f, LOCK_EX );
	sleep( 1 );
	passthru( "echo Hello" );
} else {
	$self = $_SERVER['SCRIPT_NAME'];
	echo <<<EOT
<html>
<frameset rows="50%, 50%">
<frame src="$self?f=1"/>
<frame src="$self?f=2"/>
</frameset>
</html>
EOT;
}
?>


Expected result:
----------------
The two frames should both display "Hello", after a delay of 2 seconds.

Actual result:
--------------
The frames take forever to load. Requires a force quit of Apache. 

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-07-22 15:30 UTC] jani@php.net
Isn't this just expected behaviour if you're not checking whether the flock call fails or not??
 [2007-07-22 18:44 UTC] tstarling at wikimedia dot org
I don't really understand what you mean, but I'll take a few guesses:

* flock alone is working perfectly, it does not fail. If you replace the passthru() with print(), then the whole thing will work as expected. 
* The problem doesn't appear to be that passthru() is globally synchronised. The second thread never gets to the passthru() call, you could remove it altogether for f=2 and you would still see the deadlock.
* This bug provides the possibility for a DoS attack against any script that calls session_start() followed by a shell execution function. max_execution_time is ignored. Are you telling me that the expected behaviour for this simple script:

<?php session_start(); sleep(1); passthru('hello');?> 

is to consistently deadlock on Windows whenever concurrent requests are sent?
 [2007-10-22 11:31 UTC] jani@php.net
You should call session_write_close() whenever you have something like frames / simultaneous connections to same stuff using same session id.
I bumped into similar deadlock issue myself but it was easily solved by calling session_write_close() before doing file_get_contents(). 

Expected behaviour -> not bug.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 00:01:30 2024 UTC