HTTPS clone URL

Subversion checkout URL

Summary:
The file repository uses ReadWrite lock in order to allow multiple read
operation (e.g., parsing files) at the same time. Only when the file
repository metadata needs to be updated, a write lock is needed. However,
an warning/error raised during parsing while a thread holds the read lock
can trigger a recursive parsing. This happens when the user error handler
is invoked. Deadlock happens when the thread already holds a read lock and
tries to acquire a write lock. I noticed that the parsing can be made
lock free rather than under a read lock so I restructured the code to make
it so. I also made the change to use Logger::Warning instead of raise_warning
when the maximum # of user function id is reached because that is an internal
limit and should not be handled by a user handler. Finally, fixed some
off-by-one assertion failures under DEBUG mode.
Test Plan:
make fast_tests
start hphpi in sandbox mode and browse the site
run server mode test to finish with no deadlock or crash
the test case that can lead to deadlock:
[] cat test.php
<?php
function myErrorHandler($errno, $errstr, $errfile, $errline) {
require_once('junk.php');
var_dump($errstr, $errline);
}
set_error_handler('myErrorHandler');
include_once('hello.php');
[] cat hello.php
<?php
function f1() {}
function f2() {}
function f3() {}
function f4() {}
function f5() {}
function f6() {}
echo "hello, world\n";
[] cat junk.php
<?php
echo "junk\n";
Start hphpi in sandbox mode with -v Eval.MaxUserFunctionId=5
Before the fix, the command GET http://<sandbox>/test.php will hang and
gdb attach the server confirms the deadlock. After the fix it no longer
deadlock (even without the raise_warning to Logger::Warning change).
Reviewers: qigao, mwilliams
Reviewed By: mwilliams
CC: hphp-diffs@lists, ps, mwilliams, amenghra
Differential Revision: 342493