neverwinter.nim icon indicating copy to clipboard operation
neverwinter.nim copied to clipboard

scriptcomp: for loop optimization causes infinite loops in certain cases

Open Daztek opened this issue 1 year ago • 1 comments

The for loop optimization added in https://github.com/niv/neverwinter.nim/pull/86 sometimes generates code that causes an infinite loop.

Disabling the optimization results in the script working correctly, when using nwn_script_comp you can pass the -O 0 flag to disable the optimization

Test script: testscript.txt

Daztek avatar Jan 12 '25 18:01 Daztek

Not only infinite loops—such loops can also completely hang the server. Also, it happens with the native toolset compiler.

I spent five days trying to find out why switching to .37 caused the server to hang.

After 100 restarts, I pinpointed the issue: an infinite loop in combination with the following instruction inside.

for (jCount = 1; jCount <= nEmptyChildSlots; jCount++)
{
    // ATTENTION: SPAWN HANGS HERE
    DelayCommand(0.0, DoSpawn(oSpawn, nTimeNow));
}

The reason it hangs the server is that DelayCommand(0.0, ...) stalls execution at the very end of the function. With an infinite loop, this results in a complete hang.

The infinite loop occurs because the counter variable does not increment and remains stuck at 1.

This happens because the variable's initialization somehow gets detached from the loop.

Here’s a specific example: if you move the initialization of the variable closer to the loop, the counter will work.

int jCount;
for (jCount = 1; jCount <= nEmptyChildSlots; jCount++)
{
    // ATTENTION: SPAWN HANGS HERE
    DelayCommand(0.0, DoSpawn(oSpawn, nTimeNow));
}

In our case, the initialization comes from the NESS spawn system at the beginning of the definition of 100+ variables.

Once you move the initialization further down, the counter starts working.

If you have any questions, I became kind of an expert in the issues, so feel free to contact me.

Image

eveferon avatar Feb 02 '25 18:02 eveferon