Page 1 of 3

Assert error during garbage collection [Solved]

Posted: Wed Apr 15, 2020 3:24 pm
by Roberthh
In my attempt to deal with the w600 port, I get sometimes an assert error, which happens during memory operations, just when the device is about or when it is to perform a garbage collection. The error message is:

Code: Select all

assertion "ATB_GET_KIND(block) == AT_HEAD" failed: file "../../py/gc.c", line 590, function: gc_free
The obvious message is, that the memory is somehow corrupted. But:
I happens when I call a short test script, let's call it test(), which save a few lines of text to a file. It ONLY happens when I execute this script's function by calling it from the REPL prompt manually by entering test() over and over. If I call this script function in a short loop, e.g. with "for _ in range(200): test()", everything runs well.
Has anyone a hint about what is memorywise different between calling from REPL and calling in a short loop?

Re: Assert error during garbage collection

Posted: Wed Apr 15, 2020 6:25 pm
by dhylands
The REPL has a history buffer where it stores some number of previous commands.

Actually, there are 2 history buffers. One is just the previous line MP_STATE_VM(repl_line).

And then readline has a history buffer called readline_hist. Using readline_hist requires a call to readline_init0. If you don't use readline, then you need to call pyexec_event_repl_init.

So I don't know if that's your problem, but it is one difference between executing from a script and from the REPL.

Re: Assert error during garbage collection

Posted: Wed Apr 15, 2020 7:39 pm
by Roberthh
Thanks, Dave. What puzzles me is, that REPL works fine, and there is little extra stuuf in that port with respect to REPL. Just the char in and out on the UART using a static buffer. No relation in any kind to the memory management and GC.

Re: Assert error during garbage collection

Posted: Wed Apr 15, 2020 8:11 pm
by Roberthh
Another observation: That happens only during automatic garbage collection, when going close to 0 or to whatever threshold is set. If I add in my python test script a gc.collect() when the memory is below a certain limit, all works well.

Re: Assert error during garbage collection

Posted: Wed Apr 15, 2020 9:12 pm
by dhylands
The heap should be in memory after all of the data and bss (worth double checking).

I'd also look closely at the stack. It normally comes out of high memory and grows towards the heap. If the stack was overflowing, it would corrupt the heap.

A common technique I use is to put a guard at the end of the stack which contains all 0x55's or some other value like that. I like to make the guard a bit largish (like 256 bytes). Then you can check the integrity periodically from within the code. If the guard is too small, then if a C code declares a stack buffer larger than your guard it can straddle the guard (still corrupting the heap) and not be detected.

Re: Assert error during garbage collection

Posted: Thu Apr 16, 2020 6:11 am
by Roberthh
Thanks. I'll check. In the case here the stack for the main task is statically allocated and at a lower address than the heap. And, as far as I could tell, stack check is enabled. But I can add the test pattern to check for changes, or increase it.

Edit: Thank you for pointing my attention to the stack setting. There was indeed an error. The documentation about the task start call of the OS seems to be wrong. While it says, that the stack size is to be given in stack units, which is an uint32 here, it actually treats the give size as bytes. So the stack pointer for the task was initialized wrong. But it did not solve the initial problem, sigh!

Re: Assert error during garbage collection

Posted: Thu Apr 16, 2020 7:41 pm
by Roberthh
Looking at the difference between REPL repeat and running in-line, there is obviously a parse_compile_execute() call in every repetition. But that usually runs well and I assume it contains nothing port specific.

Re: Assert error during garbage collection

Posted: Thu Apr 16, 2020 8:07 pm
by stijn
Reminds me somewhat of https://github.com/micropython/micropython/issues/4652 which has a bunch of interesting information in the comments on what you could check (a bit of a read though).

Re: Assert error during garbage collection

Posted: Thu Apr 16, 2020 8:41 pm
by Roberthh
Hello @stijn, thanks for the link. I contains indeed a lot of useful information. As far as I understood, this problem had been solved about a year ago, and I am using the most recent state of the repository. But the approach for the search is very useful.

Re: Assert error during garbage collection

Posted: Fri Apr 17, 2020 8:01 am
by stijn
Yes it was solved (contrary to the search for the fix, the fix itself was super simple, just forcing a function to never inline), but it only affected unix/windows ports. So I assume the root cause of what you're seeing here will be in the w600-specific gccollect.c. Maybe also something with inilining causeing a different stack layout than what microPython assumes or maybe some root pointer not being marked.