Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endless while loop inside trace() - unable to break from - suggested fix #1809

Closed
sleuthware opened this issue Apr 29, 2020 · 2 comments
Closed

Comments

@sleuthware
Copy link

sleuthware commented Apr 29, 2020

Wed 2020.04.29

This observation locates the reason, not the cause.

While attempting to resolve what was believed to be a garbage collection issue, as another user had posted an issue here around the same time as my discovery,

unrelated March 2 'Stack overflow when Garbage Collecting giant linked list #1765'

a trace() resulted in an endless loop. See thread:

Multiple occurances during a trace() output request along with suggested fix

I discovered the reason trace gets stuck in an endless loop.

Using link from Hardware Reference:

https://github.com/espruino/Espruino/blob/master/src/jswrap_interactive.c#L107
Clicking on the Right facing arrow takes me to the source:

Using VSCode
jsvar.c
L3544
int _jsvTraceGetLowestLevel(JsVar *var, JsVar *searchVar) {

L3561
while (childRef) {

L3565
childRef = jsvGetNextSibling(child);

ref: static ALWAYS_INLINE JsVarRef jsvGetNextSibling(const JsVar *v) { return v->varData.ref.nextSibling; }

At GitHub
https://github.com/espruino/Espruino/blob/master/src/jsvar.c#L3588

And here we have an endless loop, should 'childRef' always be non zero. This does work, when the tree is in tact, but under a condition, still to be uncovered, as long as that argument is 'truthy' this
while can never exit. I always use an external software watchdog for while conditions, and try to avoid using while in the first place, as we humans can never predict all eventualities, and to be safe, use an additional counter to bail.

Through coercion, we know that an object is coerced to a string, then is coerced to a number, the conditional test is then evaluated on that number. Since the function jsvGetNextSibling is always pointing to it's array contents, it never returns null, undefined or NaN, and therefore isn't providing a zero value either.

Even more dangerous is a while constructed inside a recursive process.

ref
https://javascript.info/ifelse
https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

Under 99.8% of cases this situation will never be encountered. For some reason, still unkown as of this date, memory becomes corrupt, providing an incorrect tree to the trace() function.

@gfwilliams
Copy link
Member

gfwilliams commented Apr 30, 2020

Through coercion, we know that an object is coerced to a string, then is coerced to a number, the conditional test is then evaluated on that number

We are talking about C code here, so I'm not sure I understand what you mean. This obviously does work in the vast majority of cases because it's used all the time and this is the first time in 7 years anyone has reported an issue.

should 'childRef' always be non zero

But it won't be unless something has gone horribly wrong.

Let's discuss this on your forum post for now.

@gfwilliams
Copy link
Member

gfwilliams commented May 4, 2020

Ok, so no steps to reproduce

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants