03-27-2021 20:18
03-27-2021 20:18
I'm getting some unexpected behavior when using async functions.
testAsync(0);
async function testAsync(i){
i++;
console.log("async " + i);
if (i < 4)
await testAsync(i);
}
results in
[4:55:56 AM]async 1
[4:55:56 AM]async 2
[4:55:56 AM]async 3
[4:55:56 AM]Terminating app: Memory fault (stack overflow?)
I would expect a lot more than three calls before reaching a stack overflow. This is indeed the case when using a synchronous function:
testSync(0);
function testSync(i){
i++;
console.log("sync " + i);
if (i < 25)
testSync(i);
}
This gets all the way to 22 before termination.
The thing I find really surprising though is that you can actually go much higher than that, by using an asynchronous function with a sleep function:
testAsyncWithSleep(0);
async function testAsyncWithSleep(i){
i++;
console.log("async/sleep " + i);
await SleepAsync(1); // fixes the issue???
if (i < 400)
await testAsyncWithSleep(i);
}
async function SleepAsync(milliseconds) {
return new Promise(resolve => {
setTimeout(() => {
resolve(true);
}, milliseconds);
});
}
This gets up all the way to 126 before being terminated, but it's also with a different error message:
[...]
[5:07:49 AM]async/sleep 126
[5:07:53 AM]Fatal Jerryscript Error: ERR_OUT_OF_MEMORY
So what gives? Why is the stack limit only three when there's no sleep during it?
P.S. I'd find it really useful if the stack overflow message could be less vague, as it's really difficult to debug with basically zero information on what's wrong.
02-02-2022 11:09
02-02-2022 11:09
Hello,
I had the error Terminating app: Memory fault (stack overflow?) too with RxJs on the watch side. I had to add your sleep function to force the execution to be async and the problem was resolved for now.
// INFO: delay the subscription to the observables.
setTimeout(() => {
// INFO: Merge changes
messagesObservable
.pipe(
map(x => stateService.update(state => { return { ...state, ...x } })),
throttleTime(1000)
)
.subscribe({
async next(x) {
await forceSwitchContext(); // <--------- the fix
ui.render(x);
// vibration.start('ring');
},
error: x => console.error(x)
});
}, 1);
render: (state) => {
if (!state) {
throw new Error('The argument state was undefined');
}
if (!isInitialized) {
throw new Error('The UI service was not initialized.');
}
const { items: localItems } = state;
// INFO: Update the local items.
items.clear();
localItems.copyTo(items);
// INFO: Trigger the update the virtual list.
list.length = items.length; // <------ CRASH HERE without the fix
}