Bug #31749 [ReO]: deadlock due to libc mutexes not released when timeout signal is delivered

2012-02-14 Thread jpauli
Edit report at https://bugs.php.net/bug.php?id=31749edit=1

 ID: 31749
 Updated by: jpa...@php.net
 Reported by:phpbug2 at mailinator dot com
 Summary:deadlock due to libc mutexes not released when
 timeout signal is delivered
 Status: Re-Opened
 Type:   Bug
 Package:Scripting Engine problem
 Operating System:   Linux 2.4.28, 2.4.21-SMP
 PHP Version:5CVS, 4CVS (2005-06-19)
 Assigned To:dmitry
 Block user comment: N
 Private report: N

 New Comment:

Interesting as well as weird bug.
I have nothing to say about it that would move things forward but that signal 
handling have been rewritten in PHP5.4. It might handle such cases, see with 
contributors.

You should have a look at http://lxr.php.net/xref/PHP_5_4/Zend/zend_signal.c 
and 
try to reproduce the bug on a 5.4 basis.


Previous Comments:

[2011-11-17 01:34:38] tstarl...@php.net

I added a workaround to our custom error handler:

https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103433


[2011-11-16 10:22:13] tstarl...@php.net

The suggested patch is an improvement, but it still calls zend_timeout() when 
the hard timeout is reached, which will usually deadlock if a libc mutex such 
as the one for malloc() is held. The only safe way to handle this situation is 
to kill the process without calling any non-signal-safe functions, e.g. by 
calling abort(). If you return control to Apache using longjmp() (like what 
zend_bailout() does), Apache will deadlock instead. I haven't found any robust 
way to display an error message, it would look the same as a segfault to the 
user.


[2010-06-08 13:27:41] michael at makeweb dot no

I have the same problem, reproduced on php 4.4.9 and 5.3.0.

Basically pseudocode to reproduce is set_time_limit(1); do { ... } until time 
passed = 1 second.

This will create a race condition where sometimes a libc lock will prevent 
zend_timeout to process properly.

Script to reproduce on 5.3.0: ($limit is not 1, because php seems to not break 
accurately on time - this value must be adjusted so the error PHP Fatal error: 
 Maximum execution time of 1 second exceeded in Unknown on line 0 frequently 
appears. The script should fail within 100 runs (lock up).

?php
  echo Trying to break php...\n;
  set_time_limit(1);
  $limit = 1.235;
  $start = array_sum(explode(' ',$x = microtime()));
  $a = array();
  for ($cnt = 0; $cnt  10; $cnt++) {
for ($cntb = 0; $cntb  100; $cntb++) {
  for ($cntc = 0; $cntc  100; $cntc++) {
$end = array_sum(explode(' ',$y = microtime()));
$a[$cnt][$cntb][$cntc] = md5($cnt.$cntb.$cntc);
if ($end = $start+$limit) break;   
  }
  if ($end = $start+$limit) break;   
}
if ($end = $start+$limit) break;   
  }
  echo $x - $y (.($end-$start).)\n;
?

run with: while [ true ]; do php break.php; done

Though this scenario is unlikely, there are other cases where it can happen 
very often, however I fail to come up with a short example of it. The reason 
for generating a multidimensional array is that in php4, the hang is very 
likely to happen within zend_shutdown, as the resources are freed (hangs within 
1-10 cycles)

Keep in mind error logging has to be enabled (this is when there's calls for 
libc get time which causes the locking issue within zend_timeout)

pstack for php 5.3.0:

# pstack 1565
#0  0x00319402 in __kernel_vsyscall ()
#1  0x001dede3 in __lll_lock_wait_private () from /lib/libc.so.6
#2  0x0016e6f6 in _L_lock_15330 () from /lib/libc.so.6
#3  0x0016dbb4 in free () from /lib/libc.so.6
#4  0x0012067c in setlocale () from /lib/libc.so.6
#5  0x08084586 in seek_to_tz_position ()
#6  0x08084664 in timelib_timezone_id_is_valid ()
#7  0x0806575c in guess_timezone ()
#8  0x080657a5 in get_timezone_info ()
#9  0x08067f35 in php_format_date ()
#10 0x082ab96e in php_log_err ()
#11 0x082abe17 in php_error_cb ()
#12 0x082f9fe8 in zend_error_noreturn ()
#13 0x082ec745 in zend_timeout ()
#14 signal handler called
#15 0x00169c49 in _int_free () from /lib/libc.so.6
#16 0x0016dbc0 in free () from /lib/libc.so.6
#17 0x082ac6df in php_conv_fp ()
#18 0x082ad409 in strx_printv ()
#19 0x082ad804 in ap_php_snprintf ()
#20 0x082565f2 in _php_gettimeofday ()
#21 0x08342509 in zend_do_fcall_common_helper_SPEC ()
#22 0x08319f3d in execute ()
#23 0x082f8e47 in zend_execute_scripts ()
#24 0x082a92be in php_execute_script ()
#25 0x08378457 in main ()

Any suggestions how to patch php4 be greatly appreciated!

Michael


[2008-07-21 01:00:00] php-bugs at lists dot php dot net

No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are 

Bug #31749 [ReO]: deadlock due to libc mutexes not released when timeout signal is delivered

2012-02-14 Thread jpauli
Edit report at https://bugs.php.net/bug.php?id=31749edit=1

 ID: 31749
 Updated by: jpa...@php.net
 Reported by:phpbug2 at mailinator dot com
 Summary:deadlock due to libc mutexes not released when
 timeout signal is delivered
 Status: Re-Opened
 Type:   Bug
 Package:Scripting Engine problem
 Operating System:   Linux 2.4.28, 2.4.21-SMP
 PHP Version:5CVS, 4CVS (2005-06-19)
 Assigned To:dmitry
 Block user comment: N
 Private report: N

 New Comment:

Seems like there are problems with 5.4 zend signals.
http://marc.info/?l=php-internalsm=132921501729587

Also, see related #61067


Previous Comments:

[2012-02-14 10:10:31] jpa...@php.net

Interesting as well as weird bug.
I have nothing to say about it that would move things forward but that signal 
handling have been rewritten in PHP5.4. It might handle such cases, see with 
contributors.

You should have a look at http://lxr.php.net/xref/PHP_5_4/Zend/zend_signal.c 
and 
try to reproduce the bug on a 5.4 basis.


[2011-11-17 01:34:38] tstarl...@php.net

I added a workaround to our custom error handler:

https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103433


[2011-11-16 10:22:13] tstarl...@php.net

The suggested patch is an improvement, but it still calls zend_timeout() when 
the hard timeout is reached, which will usually deadlock if a libc mutex such 
as the one for malloc() is held. The only safe way to handle this situation is 
to kill the process without calling any non-signal-safe functions, e.g. by 
calling abort(). If you return control to Apache using longjmp() (like what 
zend_bailout() does), Apache will deadlock instead. I haven't found any robust 
way to display an error message, it would look the same as a segfault to the 
user.


[2010-06-08 13:27:41] michael at makeweb dot no

I have the same problem, reproduced on php 4.4.9 and 5.3.0.

Basically pseudocode to reproduce is set_time_limit(1); do { ... } until time 
passed = 1 second.

This will create a race condition where sometimes a libc lock will prevent 
zend_timeout to process properly.

Script to reproduce on 5.3.0: ($limit is not 1, because php seems to not break 
accurately on time - this value must be adjusted so the error PHP Fatal error: 
 Maximum execution time of 1 second exceeded in Unknown on line 0 frequently 
appears. The script should fail within 100 runs (lock up).

?php
  echo Trying to break php...\n;
  set_time_limit(1);
  $limit = 1.235;
  $start = array_sum(explode(' ',$x = microtime()));
  $a = array();
  for ($cnt = 0; $cnt  10; $cnt++) {
for ($cntb = 0; $cntb  100; $cntb++) {
  for ($cntc = 0; $cntc  100; $cntc++) {
$end = array_sum(explode(' ',$y = microtime()));
$a[$cnt][$cntb][$cntc] = md5($cnt.$cntb.$cntc);
if ($end = $start+$limit) break;   
  }
  if ($end = $start+$limit) break;   
}
if ($end = $start+$limit) break;   
  }
  echo $x - $y (.($end-$start).)\n;
?

run with: while [ true ]; do php break.php; done

Though this scenario is unlikely, there are other cases where it can happen 
very often, however I fail to come up with a short example of it. The reason 
for generating a multidimensional array is that in php4, the hang is very 
likely to happen within zend_shutdown, as the resources are freed (hangs within 
1-10 cycles)

Keep in mind error logging has to be enabled (this is when there's calls for 
libc get time which causes the locking issue within zend_timeout)

pstack for php 5.3.0:

# pstack 1565
#0  0x00319402 in __kernel_vsyscall ()
#1  0x001dede3 in __lll_lock_wait_private () from /lib/libc.so.6
#2  0x0016e6f6 in _L_lock_15330 () from /lib/libc.so.6
#3  0x0016dbb4 in free () from /lib/libc.so.6
#4  0x0012067c in setlocale () from /lib/libc.so.6
#5  0x08084586 in seek_to_tz_position ()
#6  0x08084664 in timelib_timezone_id_is_valid ()
#7  0x0806575c in guess_timezone ()
#8  0x080657a5 in get_timezone_info ()
#9  0x08067f35 in php_format_date ()
#10 0x082ab96e in php_log_err ()
#11 0x082abe17 in php_error_cb ()
#12 0x082f9fe8 in zend_error_noreturn ()
#13 0x082ec745 in zend_timeout ()
#14 signal handler called
#15 0x00169c49 in _int_free () from /lib/libc.so.6
#16 0x0016dbc0 in free () from /lib/libc.so.6
#17 0x082ac6df in php_conv_fp ()
#18 0x082ad409 in strx_printv ()
#19 0x082ad804 in ap_php_snprintf ()
#20 0x082565f2 in _php_gettimeofday ()
#21 0x08342509 in zend_do_fcall_common_helper_SPEC ()
#22 0x08319f3d in execute ()
#23 0x082f8e47 in zend_execute_scripts ()
#24 0x082a92be in php_execute_script ()
#25 0x08378457 in main ()

Any suggestions how to patch php4 be greatly appreciated!


Bug #31749 [ReO]: deadlock due to libc mutexes not released when timeout signal is delivered

2012-02-14 Thread rasmus
Edit report at https://bugs.php.net/bug.php?id=31749edit=1

 ID: 31749
 Updated by: ras...@php.net
 Reported by:phpbug2 at mailinator dot com
 Summary:deadlock due to libc mutexes not released when
 timeout signal is delivered
 Status: Re-Opened
 Type:   Bug
 Package:Scripting Engine problem
 Operating System:   Linux 2.4.28, 2.4.21-SMP
 PHP Version:5CVS, 4CVS (2005-06-19)
 Assigned To:dmitry
 Block user comment: N
 Private report: N

 New Comment:

For Apache1 longjmp() problems, I added the exit_on_timeout ini switch a long 
time ago. It is a crude but effective way to deal with this.


Previous Comments:

[2012-02-14 12:15:22] jpa...@php.net

Seems like there are problems with 5.4 zend signals.
http://marc.info/?l=php-internalsm=132921501729587

Also, see related #61067


[2012-02-14 10:10:31] jpa...@php.net

Interesting as well as weird bug.
I have nothing to say about it that would move things forward but that signal 
handling have been rewritten in PHP5.4. It might handle such cases, see with 
contributors.

You should have a look at http://lxr.php.net/xref/PHP_5_4/Zend/zend_signal.c 
and 
try to reproduce the bug on a 5.4 basis.


[2011-11-17 01:34:38] tstarl...@php.net

I added a workaround to our custom error handler:

https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103433


[2011-11-16 10:22:13] tstarl...@php.net

The suggested patch is an improvement, but it still calls zend_timeout() when 
the hard timeout is reached, which will usually deadlock if a libc mutex such 
as the one for malloc() is held. The only safe way to handle this situation is 
to kill the process without calling any non-signal-safe functions, e.g. by 
calling abort(). If you return control to Apache using longjmp() (like what 
zend_bailout() does), Apache will deadlock instead. I haven't found any robust 
way to display an error message, it would look the same as a segfault to the 
user.


[2010-06-08 13:27:41] michael at makeweb dot no

I have the same problem, reproduced on php 4.4.9 and 5.3.0.

Basically pseudocode to reproduce is set_time_limit(1); do { ... } until time 
passed = 1 second.

This will create a race condition where sometimes a libc lock will prevent 
zend_timeout to process properly.

Script to reproduce on 5.3.0: ($limit is not 1, because php seems to not break 
accurately on time - this value must be adjusted so the error PHP Fatal error: 
 Maximum execution time of 1 second exceeded in Unknown on line 0 frequently 
appears. The script should fail within 100 runs (lock up).

?php
  echo Trying to break php...\n;
  set_time_limit(1);
  $limit = 1.235;
  $start = array_sum(explode(' ',$x = microtime()));
  $a = array();
  for ($cnt = 0; $cnt  10; $cnt++) {
for ($cntb = 0; $cntb  100; $cntb++) {
  for ($cntc = 0; $cntc  100; $cntc++) {
$end = array_sum(explode(' ',$y = microtime()));
$a[$cnt][$cntb][$cntc] = md5($cnt.$cntb.$cntc);
if ($end = $start+$limit) break;   
  }
  if ($end = $start+$limit) break;   
}
if ($end = $start+$limit) break;   
  }
  echo $x - $y (.($end-$start).)\n;
?

run with: while [ true ]; do php break.php; done

Though this scenario is unlikely, there are other cases where it can happen 
very often, however I fail to come up with a short example of it. The reason 
for generating a multidimensional array is that in php4, the hang is very 
likely to happen within zend_shutdown, as the resources are freed (hangs within 
1-10 cycles)

Keep in mind error logging has to be enabled (this is when there's calls for 
libc get time which causes the locking issue within zend_timeout)

pstack for php 5.3.0:

# pstack 1565
#0  0x00319402 in __kernel_vsyscall ()
#1  0x001dede3 in __lll_lock_wait_private () from /lib/libc.so.6
#2  0x0016e6f6 in _L_lock_15330 () from /lib/libc.so.6
#3  0x0016dbb4 in free () from /lib/libc.so.6
#4  0x0012067c in setlocale () from /lib/libc.so.6
#5  0x08084586 in seek_to_tz_position ()
#6  0x08084664 in timelib_timezone_id_is_valid ()
#7  0x0806575c in guess_timezone ()
#8  0x080657a5 in get_timezone_info ()
#9  0x08067f35 in php_format_date ()
#10 0x082ab96e in php_log_err ()
#11 0x082abe17 in php_error_cb ()
#12 0x082f9fe8 in zend_error_noreturn ()
#13 0x082ec745 in zend_timeout ()
#14 signal handler called
#15 0x00169c49 in _int_free () from /lib/libc.so.6
#16 0x0016dbc0 in free () from /lib/libc.so.6
#17 0x082ac6df in php_conv_fp ()
#18 0x082ad409 in strx_printv ()
#19 0x082ad804 in ap_php_snprintf ()
#20 0x082565f2 in _php_gettimeofday ()