lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Coroutines once stated:
> On Wed, Jul 9, 2014 at 7:19 PM, Hao Wu <wuhao.wise@gmail.com> wrote:
> 
> > I am not sure about any particular case to intend overflowing the call
> > stack, but here is to threshold the recursive looking up to 100 or something
> > - note that __index can be a function that does anything, a.k.a. unavoidable
> > infinite loop.
> 
> A stack overflow is something I might want to catch within pcall(), is
> what I am saying.  

  You can catch a Lua stack overflow with pcall().

	depth = 0
	function foo() depth = depth + 1 foo() end
	okay,err = pcall(foo)
	print(depth,okay,err)
	19996   false   stdin:1: stack overflow

> Someone a day ago in #lua told me that there is a limit on the recursion
> depth of C function calls, or something like it.

  Yes, it's the size of the program stack (on a Unix system, you can see the
default value with the command line "ulimit -s"---be aware the return value
is measured in kilobytes), minus the stack frames to the recursive function,
divided by the stack frame size of the recursive function.  It might be a
sizable number (on the system I ran the code below on, it was 1,449,652
calls before it failed, but the default stack size is limited; your milage
may vary [4]).

  And you can't portably catch a C stack overflow.  There are ways of doing
it [1] but they're system specific.  You might think you can do:

	/* PURE SWEET C89 CODE */
	#include <signal.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <setjmp.h>

	unsigned long depth;
	jmp_buf       trouble;
   
	void segv(int sig)
	{
	  longjmp(trouble,1);  
	}
    
	void foo(void)
	{
	  depth++;
	  foo();  
	}
 
	int main(void)
	{
	  if (setjmp(trouble) != 0)
	  {
	    printf("%lu\n",depth);
	    return EXIT_FAILURE;  
	  }

	  if (signal(SIGSEGV,segv) == SIG_ERR)
	  {       
	    perror("signal()");
	    return EXIT_FAILURE;
	  } 
	   
	  foo();
	  return EXIT_SUCCESS;
	}

but it won't work.  On systems without memory protection, at best, the code
will fall into an infinite loop; at worse, it might corrupt the entire
system [2].  On systems with memory protection [3] it won't corrupt the
system, but it probably won't work as intended.  When I ran this, I kept
getting "Segmentation fault (core dumped)" because:  when I ran out of stack
space, there was no space to save the CPU state before calling my signal
handler, so I was most likely getting a double fault.  

> I wasn't happy about that because I was trying to port something
> I saw in javascript so I could find the maximum recursion depth before
> stack overflow.  I wouldn't do it with __index, but infinite loops are
> sometimes desired is all I am saying.  I wouldn't limit something
> because I think others might not want that ~

  Intentional infinite loops are okay; it's the unintentional ones that
suck.

  -spc (Stupid computers and their finite memory!)

[1]	And I don't recommend it.  No, really, don't do it.

[2]	If it hits memory mapped I/O, for instance.

[3]	And I did run this code on such a system

[4]	When I set the stack size to unlimited, I reached 268,400,386 calls
	before I got a SIGBUS error, and the system seized up for about two
	minutes as a metric butload of memory was paged and back again.