Hi,
In the last days I've exchanged some e-mails with PCRE's author because of
one more bug that appeared in our database about segfaults in PCRE (related
to stack overflows).
PCRE can consume a lot of stack, because of backtracking (thus segfaulting
PHP). Yesterday I've discovered that when using the setrlimit() function,
most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)
But I was thinking why we can't fail more silently from segfaults. A
recursive PHP function can easily segfault PHP. Why can't we catch the
signal and recover from the error? (and print a "stack overflow" message,
like java does).
I've done a little program for fun to show myself how to catch the SIGSEGV
signals and print a nice message.
(http://mega.ist.utl.pt/~ncpl/break-stack.html)
So, catching the signal is easy. What about recovery? Doesn't anyone has
experience in this area? Can this be done? (and in most
SAPIs/architectures?)
Nuno
P.S.: sorry if my "bright" idea is dumb and/or undoable :)
Nuno Lopes wrote:
Hi,
In the last days I've exchanged some e-mails with PCRE's author because
of one more bug that appeared in our database about segfaults in PCRE
(related to stack overflows).
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)But I was thinking why we can't fail more silently from segfaults. A
recursive PHP function can easily segfault PHP. Why can't we catch the
signal and recover from the error? (and print a "stack overflow"
message, like java does).
Because catching these kinds of signals is a nightmare. In this
particular instance it may work because your stack hasn't been trashed,
but in many other cases it simply isn't safe to try to execute further
code. I don't know how many times I have had to go through and get rid
of some programmer's misguided idea that trying to catch and handle a
SEGV nicely was a good idea. An infinitely chain of segfaults in your
segfault handler is impossible to avoid and is much much worse than just
dropping a core as fast as possible and exiting. Any such handler also
tends to obscure the actual problem making it much more difficult to
examine the core file later.
-Rasmus
Nuno Lopes wrote:
In the last days I've exchanged some e-mails with PCRE's author because
of one more bug that appeared in our database about segfaults in PCRE
(related to stack overflows).
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)
This sounds like an interesting idea, I think we need to consider it
doing for PHP in general rather then jut when PCRE is being used. The
only thing is that rather then setting the stack to infinity, perhaps a
small value can be used ;-)
I've done a little program for fun to show myself how to catch the
SIGSEGV
signals and print a nice message.
(http://mega.ist.utl.pt/~ncpl/break-stack.html)So, catching the signal is easy. What about recovery? Doesn't anyone has
experience in this area? Can this be done? (and in most
SAPIs/architectures?)
After SEGV or any memory problem has happened the situation is
undefined. Another words you cannot reliably continue the operation of
the program. Which is why termination and dumping of core is the lesser
of all evils in this case.
Ilia
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
[response is at the bottom]
Ilia Alshanetsky wrote:
Nuno Lopes wrote:
In the last days I've exchanged some e-mails with PCRE's author
because of one more bug that appeared in our database about segfaults
in PCRE (related to stack overflows).
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)This sounds like an interesting idea, I think we need to consider it
doing for PHP in general rather then jut when PCRE is being used. The
only thing is that rather then setting the stack to infinity, perhaps a
small value can be used ;-)I've done a little program for fun to show myself how to catch the
SIGSEGV
signals and print a nice message.
(http://mega.ist.utl.pt/~ncpl/break-stack.html)So, catching the signal is easy. What about recovery? Doesn't anyone
has experience in this area? Can this be done? (and in most
SAPIs/architectures?)After SEGV or any memory problem has happened the situation is
undefined. Another words you cannot reliably continue the operation of
the program. Which is why termination and dumping of core is the lesser
of all evils in this case.
Would this "reliable execution" also apply to creating the stack
overflow message and passing it the PHPs error handler?
I was just two days ago that we had, of course, an infinite recursion
bug in our software, but the application just segfaults. The hard part
was to find where it segfaults. If it would just give a tiny hint as to
where the problem might be, this would be so awesome (if, of course,
technical possible/feasable).
-
- Markus
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
- Markus
iD8DBQFD/Azr1nS0RcInK9ARAk0KAJ4wnL2pRypacl0dqFjr2Bb5EN81KwCcDmKu
kiMDEVP6pB/jYov1DCB7JSU=
=zxbn
-----END PGP SIGNATURE
Nuno Lopes wrote:
In the last days I've exchanged some e-mails with PCRE's author because
of one more bug that appeared in our database about segfaults in PCRE
(related to stack overflows).
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)This sounds like an interesting idea, I think we need to consider it doing
for PHP in general rather then jut when PCRE is being used. The only thing
is that rather then setting the stack to infinity, perhaps a small value
can be used ;-)
Using it in PCRE is expecialy important! The new PCRE release (6.6) include
a protection against stack recursion overflows, but the usual linux stack
runs out of space before the protection code is triggered :) (although this
doesn't apply on windows, I think).
My idea was to do some testing and set the stack size to a reasonable limit
that would allow the pcre's protection code to kick in before the segfault.
But to do this, we must upgrade PCRE (I already did it on my pc).
I've done a little program for fun to show myself how to catch the
SIGSEGV
signals and print a nice message.
(http://mega.ist.utl.pt/~ncpl/break-stack.html)So, catching the signal is easy. What about recovery? Doesn't anyone has
experience in this area? Can this be done? (and in most
SAPIs/architectures?)After SEGV or any memory problem has happened the situation is undefined.
Another words you cannot reliably continue the operation of the program.
Which is why termination and dumping of core is the lesser of all evils in
this case.
After reading some stuff, I think that recovering is a bit undoable (I
previously though that messing with the stack pointer would be easy...).
But setting the handler to run on a separate stack seems to be a clean and
stable solution. Its all handled by the OS. And then we could produce a nice
error message and log it (if error_log is On).
I'll also try to produce a patch for this :)
Nuno
If we do do this, please make it optional; it's bad form when a module
or a library unilaterally changes a process-wide option or setting and
impacts a system that has already been tuned; the sysadmin may already
have set up appropriate limits.
--Wez.
Nuno Lopes wrote:
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)This sounds like an interesting idea, I think we need to consider it
doing for PHP in general rather then jut when PCRE is being used. The
only thing is that rather then setting the stack to infinity, perhaps a
small value can be used ;-)
Hi,
The problem is that setrlimit() need privilege to expand the process stack.
I don't think it's a good idea to use this system call to fix the
too-high-function-stack bug.
There is no really way to fix correctly this bug.
However I think we should re-examined the execution flow of PECL functions.
It is not normal PECL can eat all the stack.
-michael
----- Original Message -----
From: "Wez Furlong" kingwez@gmail.com
To: "Ilia Alshanetsky" ilia@prohost.org
Cc: "Nuno Lopes" nlopess@php.net; "PHPdev" internals@lists.php.net
Sent: Thursday, February 23, 2006 5:29 AM
Subject: Re: [PHP-DEV] recover from a segfault
If we do do this, please make it optional; it's bad form when a module
or a library unilaterally changes a process-wide option or setting and
impacts a system that has already been tuned; the sysadmin may already
have set up appropriate limits.
--Wez.
Nuno Lopes wrote:
PCRE can consume a lot of stack, because of backtracking (thus
segfaulting PHP). Yesterday I've discovered that when using the
setrlimit() function, most segfaults can be avoided
(http://mega.ist.utl.pt/~ncpl/php_pcre_stack_limits.txt) :)This sounds like an interesting idea, I think we need to consider it
doing for PHP in general rather then jut when PCRE is being used. The
only thing is that rather then setting the stack to infinity, perhaps a
small value can be used ;-)