|Subject:||bug#31995: 26.1; Condition-case failed to catch error|
|Date:||Thu, 12 Jul 2018 17:29:44 -0700|
|User-agent:||Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0|
@Paul Eggert: I am cc-ing you because you are the author of commit f0a1e9ec and may be more familiar with this topic.
Please ignore my previous email, I thought condition-case WAS able to catch C stack overflow before commit f0a1e9ec, but it seems not the case, or at least not related to this bug.
After some code reading and debugging, I find the problem: in commit f0a1e9ec, the read_buffer for read1 is moved from a static variable to an array stackbuf of size MAX_ALLOCA located on stack. MAX_ALLOCA is defined to be 16 * 1024. So every recursion of read1 will eat up 16KB of stack, and thousands of recursions (not uncommon for a deeply nested structure) quickly use up whole stack and cause stack overflow.
One solution is to make stackbuf much smaller. I set it to 16, and this bug disappeared. Though 16 may be too aggressive, 16 * 1024 is way too big for a stack-based buffer in a function that may recur thousands of times. To make things worse, the buffer is totally a waste of space when read1 is dealing with everything ("[", "]", "(", ")", "#", "=", numbers, etc.) other than the name of a symbol (usually tens of characters) or a string, which is the only case when we would need a really long buffer. A conservative choice would be a number higher than 40 or 80, making the buffer long enough to hold any symbol, as people usually do not have symbol longer than the one of half the width of a terminal. A more aggressive choice is to totally remove the buffer and only allocate it on heap. This comes at a cost of possible slow down because memory allocation on heap is usually slower than on stack. The reason why this was not the case before commit f0a1e9ec is that this buffer is reused by every recursion of read1, and is not a problem.
As a reference, MAX_ALLOCA is defined in src/lisp.h for SAFE_ALLOCA, which allocate memory on stack if its size is less than MAX_ALLOCA, and allocate memory on heap otherwise. The usage for SAFE_ALLOCA and a preparation macro USE_SAFE_ALLOCA seems pretty complicated and I am not able to figure out.
On 07/11/2018 10:46 PM, Sheng Yang (杨圣) wrote:
-- Sheng Yang(杨圣) PhD student Computer Science Department University of Maryland, College Park E-mail:address@hidden
|[Prev in Thread]||Current Thread||[Next in Thread]|