[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Segfault on recursive trap/kill
From: |
Bob Proulx |
Subject: |
Re: Segfault on recursive trap/kill |
Date: |
Mon, 8 Oct 2018 11:59:53 -0600 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
Mike Gerwitz wrote:
> Bob Proulx wrote:
> > Let me give the discussion this way and I think you will be
> > convinced. :-)
>
> Well, thanks for taking the time for such a long reply. :)
>
> > How is your example any different from a C program? Or Perl, Python,
> > Ruby, and so forth? All of those also allow infinite recursion and
> > the kernel will terminate them with a segfault. Because all of those
> > also allow infinite recursion. A program that executes an infinite
> > recursion would use infinite stack space. But real machines have a
> > finite amount of stack available and therefore die when the stack is
> > exceeded.
>
> I expect this behavior when writing in C, certainly. But in languages
> where the user does not deal with memory management, I'm used to a more
> graceful abort when the stack gets out of control. A segfault means
> something to a C hacker. It means very little to users who are
> unfamiliar with the concepts that you were describing.
>
> I don't have enough experience with Perl, Python, or Ruby to know how
> they handle stack issues. But, out of interest, I gave it a try:
Some of those must be maintaining the stack in program data space
instead of in the machine stack space. (shrug)
> $ perl -e 'sub foo() { foo(); }; foo()'
> Out of memory!
Perl apparently will let you use all available memory without
limitation.
> $ python <<< 'def foo():
> > foo()
> >foo()' |& tail -n1
> RuntimeError: maximum recursion depth exceeded
>...
I wonder how they decide to set the depth.
> $ php -r 'function foo() { foo(); } foo();'
>
> Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to
> allocate 262144 bytes) in Command line code on line 1
134M seems arbitrarily small but at least it does say exactly what it
is doing there.
> $ guile -e '(let x () (+ (x)))'
> allocate_stack failed: Cannot allocate memory
> Warning: Unwind-only `stack-overflow' exception; skipping pre-unwind
> handler.
>
> $ emacs --batch --eval '(message (defun foo () (foo)) (foo))'
> Lisp nesting exceeds ‘max-lisp-eval-depth’
I think these two are different. It looks like guile is using
libunwind to set up a stack exception handler whereas emacs appears to
be using a tracked max-lisp-eval-depth variable defaulting to 800 on
my system in emacs v25.
This limit serves to catch infinite recursions for you before they cause
actual stack overflow in C, which would be fatal for Emacs.
You can safely make it considerably larger than its default value,
if that proves inconveniently small. However, if you increase it too far,
Emacs could overflow the real C stack, and crash.
> I understand that in C you usually don't manage your own stack and,
> consequently, you can't say that it falls under "memory management" in
> the sense of malloc(3) and brk(2) and such. But C programmers are aware
> of the mechanisms behind the stack (or at least better be) and won't be
> surprised when they get a segfault in this situation.
>
> But if one of my coworkers who knows some web programming and not much
> about system programming gets a segfault, that's not a friendly
> error. If Bash instead said something like the above languages, then
> that would be useful.
>
> When I first saw the error, I didn't know that my trap was
> recursing. My immediate reaction was "shit, I found a bug". Once I saw
> it was the trap, I _assumed_ it was just exhausting the stack, but I
> wanted to report it regardless, just in case; I didn't have the time to
> dig deeper, and even so, I wasn't sure if it was intended behavior to
> just let the kernel handle it.
My interpretation of the above is that you would want bash to use
libunwind (or whatever is appropriate) to set up a stack overflow
exception trap in order to handle stack overflow specially and then to
make an improved error reporting to the user when it happens.
Frankly I wasn't even aware of libunwind before this. And haven't
learned enough about it to even know if that is what I should be
mentioning here yet. :-)
> > Shell script code is program source code. Infinite loops or infinite
> > recursion are bugs in the shell script source code not the interpreter
> > that is executing the code as written.
>
> I also agree. But the context is very different. Shell is a very,
> very high-level language.
My mind reels at the statement, "Shell is a very, very high-level
language." What?! The shell is a very simple low level command and
control language. It is very good at what it does. But if one needs
to do high level things then one should switch over to a high level
language. :-)
> > Hope this helps!
>
> There was useful information, yes.
After sifting out the non-useful information. :-)
> I hope I was able to further clarify my concerns as well.
You are always eloquent! :-)
Bob
signature.asc
Description: PGP signature
Re: Segfault on recursive trap/kill, Robert Elz, 2018/10/06