This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Yarillo's profile picture

[1.74][SMP+SSP]This code crashes the computer with no errors even though it should work

Started by Yarillo, 03 August 2015 - 02:41 PM
Yarillo #1
Posted 03 August 2015 - 04:41 PM
VERSION:
1.74
REPRODUCTION STEPS:

old = {}
old.turtle = turtle

function inspect()
  return old.turtle.inspect()
end
turtle.inspect = inspect

print(tostring(turtle.inspect()))
EXPECTED RESULT:
prints "true" or "false" depending on what's in front of the turtle

ACTUAL RESULT:

screen goes black, nothing happens, can't reboot, can't shut down, can't stop the script. Eventually, it reboots by itself.

PS: If you break the turtle while the screen is black, if you place it back (even in another spot) the script seems to still run. It still eventually stops. Also, once you did that, if you place another turtle (I placed it in the same spot as before, maybe it has something to do with it) the same thing will happen. The turtle will take a few minutes to turn on.
MKlegoman357 #2
Posted 03 August 2015 - 05:22 PM
This isn't really a bug with CC but rather a bug with your code. This line here:


old.turtle = turtle

Doesn't copy the table 'turtle'. It copies a pointer to the table 'turtle', thus 'old.turtle' would be equal to 'turtle'. Now, the problem here is that you create a new function 'inspect' which then calls the 'old.turtle.inspect()' function. And remember that doing 'old.turtle.inspect()' is calling the same function which appears in 'turtle.inspect()'. So when you actually assign a new function to 'turtle' table you also "affect" the 'old.turtle' table (which is the exact same table), and thus calling turtle.inspect ends up calling itself, over and over again until the computer crashes.

Now, you could say that this isn't really a bug. But it surely is something that could be dealt nicer on the CC-side.
Yarillo #3
Posted 03 August 2015 - 05:28 PM
I didn't think it was a pointer. I thought it was the function itself that I duplicated. So I guess that makes sense.
Thanks !
flaghacker #4
Posted 03 August 2015 - 05:29 PM
But it surely is something that could be dealt nicer on the CC-side.

Well no, not really, that's simply how lua works.
SquidDev #5
Posted 03 August 2015 - 05:30 PM
screen goes black, nothing happens, can't reboot, can't shut down, can't stop the script. Eventually, it reboots by itself.
Now, you could say that this isn't really a bug. But it surely is something that could be dealt nicer on the CC-side.

I'm slightly surprised this happens. There is a debug hook that executes every 1000 (I think) instructions that checks to ensure the computer shouldn't timeout, but that doesn't seem to be triggered correctly. Most 'too long without yielding' errors come from CC's methods (as opposed to Lua built-ins) which check for the timeout, but as you aren't calling any you will not get it.

I'm working off memory but I think:

while true do end
Will just get a black screen, but:

while true do term.write("x") end
will not.

Infinite loops without any CC methods being called are quite rare, so this generally isn't a problem.
Edited on 03 August 2015 - 03:32 PM
Yarillo #6
Posted 03 August 2015 - 05:35 PM
There still is a problem though, no error is being displayed.
flaghacker #7
Posted 03 August 2015 - 06:10 PM
Your code is equivalent to something like this: (for the reasons explained in other posts)

local function a()
  return a()
end

a()
It's infinitely recursive, it will never return. Normally something like that results in a stackoverflow error (indexoutofbounds in computercraft). Because you managed to accidently sneak in a proper tail call this doest happen, and you simply get an infinite loop. Your code is actually equivalent to

while true do

end

This should result in an error too, a "too long without yielding". That doest happen because computercraft can only terminate your code if you use some computercraft funstions (read, monitor.write, periphera.wrap, print, anything really…). This results in strange behaviour, including other computers in your world not reacting anymore.

The fix would be to "deep copy" the turtle table, like this:


local oldT = {}

for name, function in pairs(turtle) do
  oldT[name] = function
end

turtle.inspect = function(...)
  return oldT.inspect(unpack(arg))
end

Because of bad luck you got a couple of dark computercraft concepts working against you while debugging your code, but really the only problem is you copying the table wrong. I hope I managed to explain what's going on here, but feel free to ask further questions if I wasn't understandable at all :D/>
Edited on 03 August 2015 - 04:12 PM
SquidDev #8
Posted 03 August 2015 - 06:33 PM
It's infinitely recursive, it will never return. Normally something like that results in a stackoverflow error (indexoutofbounds in computercraft). Because you managed to accidently sneak in a proper tail call this doest happen, and you simply get an infinite loop.

+1. Didn't catch that. In fact, +1 for an all-round good explanation of what occurred.
flaghacker #9
Posted 03 August 2015 - 07:06 PM
It's infinitely recursive, it will never return. Normally something like that results in a stackoverflow error (indexoutofbounds in computercraft). Because you managed to accidently sneak in a proper tail call this doest happen, and you simply get an infinite loop.

+1. Didn't catch that. In fact, +1 for an all-round good explanation of what occurred.

Hey thanks, really appreciated! I was actually about to start explaining why it doesn't cause a "too long without yielding" error when I thought "wait a sec, why no stackoverflow?" ;)/>
Lyqyd #10
Posted 03 August 2015 - 07:56 PM
Moved to Ask a Pro.