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: 2009-09-09 19:52 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: dmitry
Status: Assigned 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.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 01:02:05 2014 UTC