Bug #74878 [NEW]: Data race in ZTS builds
| From: | maroszek at gmx dot net | Date: | Fri, 07 Jul 2017 20:11:36 +0000 |
| Subject: | Bug #74878 [NEW]: Data race in ZTS builds | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-209908@lists.php.net to get a copy of this message | ||
From: maroszek at gmx dot net
Operating system: Linux/MacOS
PHP version: 7.2.0alpha3
Package: *General Issues
Bug Type: Bug
Bug description:Data race in ZTS builds
Description:
------------
Build PHP with thread sanitizer:
CFLAGS="-O1 -g -fsanitize=thread" ./configure --disable-fpm
--disable-cgi --disable-cli --disable-phpdbg --enable-embed=static
--enable-maintainer-zts --without-iconv --enable-json --enable-mbstring
Use my ZTS Embed example which produces a lot of parallel executed
scripts.
https://gist.github.com/paresy/3cbd4c6a469511ac7479aa0e7c42fea7
Build it:
clang++ crash.cpp -Imain -ITSRM -IZend -I. --std=c++11 -Llibs -lphp7
-lxml2 -lresolv -ldl -pthread -fsanitize=thread -g -O1
Run it:
./a.out
Background:
I am trying to locate random segfaults in PHP 7.2 since two weeks... and
this is the best i could find yet... (It is a lot better since 7.2!
Thanks a lot!) Valgrind shows nothing... And this only shows data
races... but i cannot reproduce a crash :( Anyway... It should be fixed
nevertheless. Hopefully the data is useful :)
Hint:
Sometimes the data race happens in zend_destroy_hash. See second log
from the output.
Test script:
---------------
<?
class JSONRPCException extends Exception {
//
}
class JSONRPC {
private $url;
private $username;
private $password;
function __construct($url) {
$data = @parse_url($url);
if(($data === false) || !isset($data['scheme']) ||
!isset($data['host']))
throw new Exception("Invalid URL");
$this->url = $data['scheme']."://".$data['host'];
if(isset($data['port']))
$this->url .= ":".$data['port'];
if(isset($data['path']))
$this->url .= $data['path'];
if(isset($data['user']))
$this->username = $data['user'];
else
$this->username = "";
if(isset($data['pass']))
$this->password = $data['pass'];
else
$this->password = "";
}
public function __call($method, $arguments) {
return self::makeRequest($this->url, $this->username,
$this->password, $method, $arguments, false);
}
static public function __callStatic($method, $params) {
return self::makeRequest("http://127.0.0.1:3777/api/", "",
"",
$method, $params, true);
}
static private function makeRequest($url, $username, $password,
$method, $params, $customErrorHandler) {
try {
if (!is_scalar($method)) {
throw new Exception('Method name has no scalar value');
}
if (!is_array($params)) {
throw new Exception('Params must be given as array');
}
$id = round(fmod(microtime(true)*1000, 10000));
$params = array_values($params);
$strencode = function(&$item, $key) {
if ( is_string($item) )
$item = utf8_encode($item);
else if ( is_array($item) )
array_walk_recursive($item, $strencode);
};
array_walk_recursive($params, $strencode);
$request = Array(
"jsonrpc" => "2.0",
"method" => $method,
"params" => $params,
"id" => $id
);
$request = json_encode($request);
$header = "Content-type: application/json"."\r\n";
if(($username != "") || ($password != "")) {
$header .= "Authorization: Basic
".base64_encode($username.":".$password)."\r\n";
}
$options = Array(
"http" => array (
"method" => 'POST',
"header" => $header,
"content" => $request
)
);
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
if($response === false)
{
throw new Exception('Unable to connect');
}
if((strpos($http_response_header[0], "200") === false)) {
throw new Exception('Server did not respond successfully');
}
$response = json_decode($response, true);
if (is_null($response)) {
throw new Exception('Request error: No response');
}
$strdecode = function(&$item, $key) {
if ( is_string($item) )
$item = utf8_decode($item);
else if ( is_array($item) )
array_walk_recursive($item, $strdecode);
};
array_walk_recursive($response, $strdecode);
if (isset($response['error'])) {
throw new JSONRPCException($response['error']['message']);
}
if (!isset($response['id'])) {
throw new Exception('No response id');
} elseif ($response['id'] != $id) {
throw new Exception('Incorrect response id (request id: ' . $id .
', response id: ' . $response['id'] . ')');
}
return $response['result'];
} catch (Exception $e) {
if($customErrorHandler) {
set_error_handler(array('JSONRPC', '__errorHandler'));
$trace = $e->getTrace();
trigger_error($e->getMessage().' in '.$trace[3]['file'].' on line
'.$trace[3]['line'], E_USER_WARNING);
restore_error_handler();
return false;
} else {
throw $e;
}
}
}
static private function __errorHandler($errno, $errstr, $errfile,
$errline)
{
if (!(error_reporting() & $errno)) {
return;
}
echo $errstr;
return true;
}
}
?>
Expected result:
----------------
No output.
Actual result:
--------------
==================
WARNING: ThreadSanitizer: data race (pid=25837)
Write of size 4 at 0x7d0800009560 by thread T2:
#0 do_inherit_property zend_inheritance.c:709
(a.out+0x000100556bb4)
#1 zend_do_inheritance zend_inheritance.c:925
(a.out+0x0001005565b1)
#2 do_bind_inherited_class zend_compile.c:1183
(a.out+0x0001004a7bcd)
#3 zend_do_early_binding zend_compile.c:1240 (a.out+0x0001004a8279)
#4 zend_compile_top_stmt zend_compile.c:8080 (a.out+0x0001004bf1d1)
#5 zend_compile_top_stmt zend_compile.c:8068 (a.out+0x0001004bf116)
#6 zend_compile zend_language_scanner.l:601 (a.out+0x000100468c77)
#7 compile_file zend_language_scanner.l:635 (a.out+0x0001004688bf)
#8 phar_compile_file phar.c:3320 (a.out+0x0001002d76d5)
#9 zend_execute_scripts zend.c:1484 (a.out+0x0001004eb4c9)
#10 php_execute_script main.c:2550 (a.out+0x00010042c815)
#11 main::$_0::operator()() const crash.cpp:35
(a.out+0x000100001ae3)
#12 void* std::__1::__thread_proxy<std::__1::tuple<main::$_0>
>(void*) thread:357 (a.out+0x0001000019c2)
Previous write of size 4 at 0x7d0800009560 by thread T1:
#0 do_inherit_property zend_inheritance.c:709
(a.out+0x000100556bb4)
#1 zend_do_inheritance zend_inheritance.c:925
(a.out+0x0001005565b1)
#2 do_bind_inherited_class zend_compile.c:1183
(a.out+0x0001004a7bcd)
#3 zend_do_early_binding zend_compile.c:1240 (a.out+0x0001004a8279)
#4 zend_compile_top_stmt zend_compile.c:8080 (a.out+0x0001004bf1d1)
#5 zend_compile_top_stmt zend_compile.c:8068 (a.out+0x0001004bf116)
#6 zend_compile zend_language_scanner.l:601 (a.out+0x000100468c77)
#7 compile_file zend_language_scanner.l:635 (a.out+0x0001004688bf)
#8 phar_compile_file phar.c:3320 (a.out+0x0001002d76d5)
#9 zend_execute_scripts zend.c:1484 (a.out+0x0001004eb4c9)
#10 php_execute_script main.c:2550 (a.out+0x00010042c815)
#11 main::$_0::operator()() const crash.cpp:35
(a.out+0x000100001ae3)
#12 void* std::__1::__thread_proxy<std::__1::tuple<main::$_0>
>(void*) thread:357 (a.out+0x0001000019c2)
Location is heap block of size 32 at 0x7d0800009560 allocated by main
thread:
#0 malloc <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x00000004188a)
#1 __zend_malloc zend_alloc.c:2811 (a.out+0x0001004a213a)
#2 zend_declare_property zend_API.c:3766 (a.out+0x0001004fa0fe)
#3 zend_declare_property_string zend_API.c:3814
(a.out+0x0001004fa47a)
#4 zend_register_default_exception zend_exceptions.c:820
(a.out+0x00010052866c)
#5 zend_register_default_classes zend_default_classes.c:34
(a.out+0x0001005558f6)
#6 zm_startup_core zend_builtin_functions.c:302
(a.out+0x000100513bf1)
#7 zend_startup_module_ex zend_API.c:1873 (a.out+0x0001004f39e6)
#8 zend_startup_module_zval zend_API.c:1888 (a.out+0x0001004f41e1)
#9 zend_hash_apply zend_hash.c:1506 (a.out+0x00010050dda6)
#10 zend_startup_modules zend_API.c:1999 (a.out+0x0001004f4007)
#11 php_module_startup main.c:2269 (a.out+0x000100429f94)
#12 php_embed_startup php_embed.c:109 (a.out+0x0001006385f1)
#13 php_embed_init php_embed.c:200 (a.out+0x0001006388d2)
#14 main crash.cpp:10 (a.out+0x000100001209)
Thread T2 (tid=2628148, running) created by main thread at:
#0 pthread_create <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x000000024410)
#1 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:369
(a.out+0x000100001936)
#2 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:365
(a.out+0x0001000018f0)
#3 std::__1::shared_ptr<std::__1::thread>
std::__1::shared_ptr<std::__1::thread>::make_shared<main::$_0>(main::$_0&&)
memory:3800 (a.out+0x0001000017b1)
#4 main crash.cpp:14 (a.out+0x00010000137a)
Thread T1 (tid=2628147, running) created by main thread at:
#0 pthread_create <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x000000024410)
#1 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:369
(a.out+0x000100001936)
#2 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:365
(a.out+0x0001000018f0)
#3 std::__1::shared_ptr<std::__1::thread>
std::__1::shared_ptr<std::__1::thread>::make_shared<main::$_0>(main::$_0&&)
memory:3800 (a.out+0x0001000017b1)
#4 main crash.cpp:14 (a.out+0x00010000137a)
SUMMARY: ThreadSanitizer: data race zend_inheritance.c:709 in
do_inherit_property
WARNING: ThreadSanitizer: data race (pid=50889)
Write of size 4 at 0x7d0800009560 by thread T1:
#0 zend_hash_destroy zend_hash.c:1268 (a.out+0x00010050cbcc)
#1 destroy_zend_class zend_opcode.c:309 (a.out+0x0001004d40a6)
#2 zend_hash_reverse_apply zend_hash.c:997 (a.out+0x00010050f926)
#3 shutdown_executor zend_execute_API.c:375 (a.out+0x0001004ca8dc)
#4 zend_deactivate zend.c:1060 (a.out+0x0001004e9ac6)
#5 php_request_shutdown main.c:1879 (a.out+0x000100428dc1)
#6 main::$_0::operator()() const crash.cpp:31
(a.out+0x0001000016ef)
#7 void* std::__1::__thread_proxy<std::__1::tuple<main::$_0>
>(void*) thread:357 (a.out+0x0001000015c2)
Previous write of size 4 at 0x7d0800009560 by thread T3:
#0 do_inherit_property zend_inheritance.c:709
(a.out+0x0001005575d4)
#1 zend_do_inheritance zend_inheritance.c:925
(a.out+0x000100556fd1)
#2 do_bind_inherited_class zend_compile.c:1181
(a.out+0x0001004a79fd)
#3 zend_do_early_binding zend_compile.c:1238 (a.out+0x0001004a80a9)
#4 zend_compile_top_stmt zend_compile.c:8073 (a.out+0x0001004befa1)
#5 zend_compile_top_stmt zend_compile.c:8061 (a.out+0x0001004beee6)
#6 zend_compile zend_language_scanner.l:601 (a.out+0x000100468aa7)
#7 compile_file zend_language_scanner.l:635 (a.out+0x0001004686ef)
#8 phar_compile_file phar.c:3320 (a.out+0x0001002d7715)
#9 zend_execute_scripts zend.c:1531 (a.out+0x0001004eba39)
#10 php_execute_script main.c:2548 (a.out+0x00010042c715)
#11 main::$_0::operator()() const crash.cpp:35
(a.out+0x0001000016e3)
#12 void* std::__1::__thread_proxy<std::__1::tuple<main::$_0>
>(void*) thread:357 (a.out+0x0001000015c2)
Location is heap block of size 32 at 0x7d0800009560 allocated by main
thread:
#0 malloc <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x00000004188a)
#1 __zend_malloc zend_alloc.c:2811 (a.out+0x0001004a1f6a)
#2 zend_declare_property zend_API.c:3746 (a.out+0x0001004fc30e)
#3 zend_declare_property_string zend_API.c:3794
(a.out+0x0001004fc68a)
#4 zend_register_default_exception zend_exceptions.c:820
(a.out+0x000100528d1c)
#5 zend_register_default_classes zend_default_classes.c:34
(a.out+0x000100556316)
#6 zm_startup_core zend_builtin_functions.c:302
(a.out+0x000100514301)
#7 zend_startup_module_ex zend_API.c:1873 (a.out+0x0001004f3f56)
#8 zend_startup_module_zval zend_API.c:1888 (a.out+0x0001004f4751)
#9 zend_hash_apply zend_hash.c:1507 (a.out+0x00010050e4b6)
#10 zend_startup_modules zend_API.c:1999 (a.out+0x0001004f4577)
#11 php_module_startup main.c:2269 (a.out+0x000100429e94)
#12 php_embed_startup php_embed.c:109 (a.out+0x0001006396b1)
#13 php_embed_init php_embed.c:200 (a.out+0x000100639992)
#14 main crash.cpp:10 (a.out+0x000100000e09)
Thread T1 (tid=2489677, running) created by main thread at:
#0 pthread_create <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x000000024410)
#1 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:369
(a.out+0x000100001536)
#2 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:365
(a.out+0x0001000014f0)
#3 std::__1::shared_ptr<std::__1::thread>
std::__1::shared_ptr<std::__1::thread>::make_shared<main::$_0>(main::$_0&&)
memory:3800 (a.out+0x0001000013b1)
#4 main crash.cpp:14 (a.out+0x000100000f7a)
Thread T3 (tid=2489679, running) created by main thread at:
#0 pthread_create <null>:144
(libclang_rt.tsan_osx_dynamic.dylib+0x000000024410)
#1 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:369
(a.out+0x000100001536)
#2 std::__1::thread::thread<main::$_0, void>(main::$_0&&) thread:365
(a.out+0x0001000014f0)
#3 std::__1::shared_ptr<std::__1::thread>
std::__1::shared_ptr<std::__1::thread>::make_shared<main::$_0>(main::$_0&&)
memory:3800 (a.out+0x0001000013b1)
#4 main crash.cpp:14 (a.out+0x000100000f7a)
SUMMARY: ThreadSanitizer: data race zend_hash.c:1268 in
zend_hash_destroy
--
Edit bug report at https://bugs.php.net/bug.php?id=74878&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=74878&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=74878&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=74878&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=74878&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=74878&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=74878&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=74878&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=74878&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=74878&r=support
Expected behavior: https://bugs.php.net/fix.php?id=74878&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=74878&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=74878&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=74878&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=74878&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=74878&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=74878&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=74878&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=74878&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=74878&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=74878&r=mysqlcfg