php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #16820 [PATCH] hangs in multithreaded environment (ZTS)
Submitted: 2002-04-25 06:24 UTC Modified: 2015-01-11 04:22 UTC
Votes:20
Avg. Score:4.3 ± 0.9
Reproduced:11 of 13 (84.6%)
Same Version:4 (36.4%)
Same OS:9 (81.8%)
From: wmeler at wp-sa dot pl Assigned: ab
Status: No Feedback Package: Scripting Engine problem
PHP Version: 5.*, 6, 7, 8.. OS: * (ZTS only)
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2002-04-25 06:24 UTC] wmeler at wp-sa dot pl
If you have bad luck and get termination signal (after exceding max_execution_time limit) in some critical section
locks won't be released !!! (because of usage of longjmp function in zend_bailout)

eg. when signal come when process is executing malloc in ealloc (Zend/zend_alloc.c) function it won't release internal
lock, and shutdown functions that free memory will hang as well as other threads.

You probably can prevent it with HANDLE_BLOCK_INTERRUPTIONS macro, but it isn't good solution.
I suggest that zend_timeout function should set EG(timed_out) flag, as it is done in windows environment. Flag should be checked in execute function (Zend/zend_execute.c) in main loop.

waiting for your patch (my is working, but is ugly coded;-)),
Wojtek

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-10-21 00:18 UTC] wmeler at wp-sa dot pl
Well, it seems that nothing has changed - on timeout it still does longjmp without care of semaphores. Locks won't be freed so it will hang. 
As I wrote few months ago, signal handler should only set EG(timeout) flag.
 [2003-07-16 01:08 UTC] sniper@php.net
Could you also tell us what configure line you have used?
(so we can try to reproduce this too before applying any patches..)

 [2003-07-21 02:07 UTC] wmeler at wp-sa dot pl
I took few days off. You know - holidays.
My config.nice :

'./configure' \
'--disable-all' \
'--with-apxs2=/usr/local/apache2/bin/apxs' \
'--with-config-file-path=/usr/local/apache2/conf/' \
'--enable-debug' \
"$@"

my script:
<?
function shutdown() {
  echo strlen($GLOBALS['a']);
}
set_time_limit(1);
register_shutdown_function('shutdown');
while (true) $a.='a';

I use apache 2.0.47 with config.nice:
"./configure" \
"--enable-so" \
"--with-mpm=worker" \
"$@"

Now I have SIGSEGVs instead of hangs :) - probably longjump hit in the middle of emalloc/erealloc and memory cache is corrupted.
I used my own module before, witch uses shared variables and locks -  thats why it hanged. Now - without my module it just crashes  :).
 [2003-07-21 02:46 UTC] wmeler at wp-sa dot pl
As I said - heap corrupted.
backtrace:

#0  0x40393966 in _efree (ptr=0x42671030, 
    __zend_filename=0x403e5840 "/tmp/php4-STABLE-200307081130/Zend/zend_execute_API.c", 
    __zend_lineno=291, 
    __zend_orig_filename=0x403e5ca0 "/tmp/php4-STABLE-200307081130/Zend/zend_variables.c", 
    __zend_orig_lineno=44) at /tmp/php4-STABLE-200307081130/Zend/zend_alloc.c:259
#1  0x403a3e18 in _zval_dtor (zvalue=0x81d6018, 
    __zend_filename=0x403e5840 "/tmp/php4-STABLE-200307081130/Zend/zend_execute_API.c", 
    __zend_lineno=291) at /tmp/php4-STABLE-200307081130/Zend/zend_variables.c:61
#2  0x4039b878 in _zval_ptr_dtor (zval_ptr=0x81d60d4, 
    __zend_filename=0x403e5ca0 "/tmp/php4-STABLE-200307081130/Zend/zend_variables.c", 
    __zend_lineno=167) at /tmp/php4-STABLE-200307081130/Zend/zend_execute_API.c:291
#3  0x403a40d2 in _zval_ptr_dtor_wrapper (zval_ptr=0x81d60d4)
    at /tmp/php4-STABLE-200307081130/Zend/zend_variables.c:167
#4  0x403aa7a3 in zend_hash_destroy (ht=0x81bfa94)
    at /tmp/php4-STABLE-200307081130/Zend/zend_hash.c:543
#5  0x4039b361 in shutdown_executor (tsrm_ls=0x81aa7f0)
    at /tmp/php4-STABLE-200307081130/Zend/zend_execute_API.c:186
#6  0x403a546d in zend_deactivate (tsrm_ls=0x81aa7f0)
    at /tmp/php4-STABLE-200307081130/Zend/zend.c:666
#7  0x40374772 in php_request_shutdown (dummy=0x0) at /tmp/php4-STABLE-200307081130/main/main.c:995
#8  0x403c4923 in php_apache_request_dtor (r=0x81a6830, tsrm_ls=0x81aa7f0)
    at /tmp/php4-STABLE-200307081130/sapi/apache2handler/sapi_apache2.c:445
#9  0x403c4c4d in php_handler (r=0x81a6830)
    at /tmp/php4-STABLE-200307081130/sapi/apache2handler/sapi_apache2.c:541
#10 0x808269e in ap_run_handler (r=0x81a6830) at config.c:194


With my patch there are almost no problems. The problem is that shutdown function won't execute - EG(timeout) flag should be cleared before execution of shutdown function.
I can correct it if you want.
 [2003-08-13 21:43 UTC] sniper@php.net
I could finally reproduce this. The patches didn't make any difference.

 [2004-01-27 03:33 UTC] wmeler at wp-sa dot pl
Zeev corrected #21513. It won't help.
As long as zend_timeout calls longjmp (through zend_error, php_error_cb and zend_bailout) shutdown functions can get memory, locks - any objects in undefined state.
2 years - no change ...
 [2009-03-10 15:38 UTC] kalle@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/

Can you try a recent snapshot? I cannot reproduce this under CLI on Ubuntu (5.3.0b1) or Windows (5.2.8) with ZTS
 [2009-03-11 09:14 UTC] wmeler at wp-sa dot pl
What should I say to make you stop using longjmp family calls in signal handler? 

IT IS NOT THREAD SAFE !!!

You probably can reproduce it with:

./configure --enable-maintainer-zts; make; sapi/cli/php ../aaa.php

Fatal error: Maximum execution time of 1 second exceeded in /root/aaa.php on line 7
6504146zend_mm_heap corrupted

aaa.php is a script posted 21 Jul 2003 2:07am UTC.
 [2009-05-11 10:40 UTC] wmeler at wp-sa dot pl
Following patch solves the problem.

diff -urN php-5.3.0RC1/Zend/zend_config.h php-5.3.0RC1/Zend/zend_config.h
--- php-5.3.0RC1/Zend/zend_config.h	1970-01-01 01:00:00.000000000 +0100
+++ php-5.3.0RC1/Zend/zend_config.h	2009-05-11 11:40:05.408398000 +0200
@@ -0,0 +1,4 @@
+#include <../main/php_config.h>
+#if defined(APACHE) && defined(PHP_API_VERSION)
+#undef HAVE_DLFCN_H
+#endif
diff -urN php-5.3.0RC1/Zend/zend_execute_API.c php-5.3.0RC1/Zend/zend_execute_API.c
--- php-5.3.0RC1/Zend/zend_execute_API.c	2009-03-19 19:34:16.000000000 +0100
+++ php-5.3.0RC1/Zend/zend_execute_API.c	2009-05-11 11:01:28.663182000 +0200
@@ -185,7 +185,7 @@
 	zend_objects_store_init(&EG(objects_store), 1024);
 
 	EG(full_tables_cleanup) = 0;
-#ifdef ZEND_WIN32
+#if defined(ZEND_WIN32) || defined(ZTS)
 	EG(timed_out) = 0;
 #endif
 
@@ -1280,6 +1280,15 @@
 }
 /* }}} */
 
+static void zend_timeout_signal_proc (int dummy) {
+	TSRMLS_FETCH();
+#ifdef ZTS
+	EG(timed_out) = 1;
+#else 
+	zend_timeout(0);
+#endif
+}
+
 #ifdef ZEND_WIN32
 static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */
 {
@@ -1424,7 +1433,7 @@
 			setitimer(ITIMER_REAL, &t_r, NULL);
 		}
 		if(reset_signals) {
-			signal(SIGALRM, zend_timeout);
+			signal(SIGALRM, zend_timeout_signal_proc`);
 			sigemptyset(&sigset);
 			sigaddset(&sigset, SIGALRM);
 		}
@@ -1432,7 +1441,7 @@
 			setitimer(ITIMER_PROF, &t_r, NULL);
 		}
 		if(reset_signals) {
-			signal(SIGPROF, zend_timeout);
+			signal(SIGPROF, zend_timeout_signal_proc);
 			sigemptyset(&sigset);
 			sigaddset(&sigset, SIGPROF);
 		}
diff -urN php-5.3.0RC1/Zend/zend_globals.h php-5.3.0RC1/Zend/zend_globals.h
--- php-5.3.0RC1/Zend/zend_globals.h	2009-03-18 11:18:09.000000000 +0100
+++ php-5.3.0RC1/Zend/zend_globals.h	2009-05-11 10:50:10.810172000 +0200
@@ -213,8 +213,10 @@
 	/* for extended information support */
 	zend_bool no_extensions;
 
-#ifdef ZEND_WIN32
+#if defined(ZEND_WIN32)||defined(ZTS)
 	zend_bool timed_out;
+#endif
+#ifdef ZEND_WIN32
 	OSVERSIONINFOEX windows_version_info;
 #endif
 
diff -urN php-5.3.0RC1/Zend/zend_vm_execute.h php-5.3.0RC1/Zend/zend_vm_execute.h
--- php-5.3.0RC1/Zend/zend_vm_execute.h	2009-03-18 19:49:27.000000000 +0100
+++ php-5.3.0RC1/Zend/zend_vm_execute.h	2009-05-11 10:48:32.487352000 +0200
@@ -95,7 +95,7 @@
 	
 	while (1) {
     	int ret;
-#ifdef ZEND_WIN32
+#if defined(ZEND_WIN32) || defined(ZTS)
 		if (EG(timed_out)) {
 			zend_timeout(0);
 		}
diff -urN php-5.3.0RC1/Zend/zend_vm_execute.skl php-5.3.0RC1/Zend/zend_vm_execute.skl
--- php-5.3.0RC1/Zend/zend_vm_execute.skl	2008-06-11 15:18:41.000000000 +0200
+++ php-5.3.0RC1/Zend/zend_vm_execute.skl	2009-05-11 10:48:59.796813000 +0200
@@ -61,7 +61,7 @@
 	
 	while (1) {
     {%ZEND_VM_CONTINUE_LABEL%}
-#ifdef ZEND_WIN32
+#if defined(ZEND_WIN32) || defined(ZTS)
 		if (EG(timed_out)) {
 			zend_timeout(0);
 		}
 [2009-09-09 19:52 UTC] jani@php.net
Dmitry, now there's patch to fix this.
 [2014-12-28 19:04 UTC] kalle@php.net
-Assigned To: dmitry +Assigned To: ab
 [2014-12-28 19:04 UTC] kalle@php.net
Antal, is this still an issue in any recent version of PHP, or after the native-tls merge? If not can you please close this report, or unassign it, thanks!
 [2014-12-28 19:41 UTC] ab@php.net
-Status: Assigned +Status: Feedback
 [2014-12-28 19:41 UTC] ab@php.net
@wmeler

Thanks for consequently staying on this issue. This is probably the best time to revisit this bug. Please note that the windows part was just reworked (usage of timer queue) and is not in any of the releases yet. Please check the latest branches starting with 5.5. Unfortunately your patch can't apply to the current sources, for the unix part i can just say - yeah, that's relevant as well. Even it'll slowdown the ZTS build, it'll stabilize it. It could be great if you could check the unix branches. Furthermore, a reproduce scenario would value in gold, not just a patch.

Thanks.
 [2014-12-28 19:51 UTC] ab@php.net
Kalle,

yeah, that's probably still an issue. Sadly TS builds are rarely utilized. The timed_out stuff was used only on Windows. I however would need a reproduce scenario for the behaviour on Unix, but that would actually be a comprehensive help, i guess.

Cheers, Anatol
 [2015-01-11 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2015 The PHP Group
All rights reserved.
Last updated: Sat May 30 06:02:31 2015 UTC