Posted 03 January 2015 - 12:28 AM
Hi there. This post is borderline to a bug report but I post this here asking for help because I have no idea what circumstances lead to the problem described. I have spent a few days on making this cool program in my own lightweight modpack in singleplayer. Now I wanted to deploy it on the server I actually play on, it uses the FTB DW20 pack for MC 1.7.10. It's version 1.0.2 of the pack and that one has CC 1.65. That's the same CC version I used in my dev world.
The problem is, in my dev world everything works great. But on the server, when I do something specific with my program (more later) I crash computercraft for the whole server. The server keeps running though and everything else still works, but all computers/turtles freeze, show the same screen they had when CC crashed and no (fresh) computers I place ever start up.
Now I would be very happy about any pointers as to what I could even do so wrong that this could happen. Since this problem clearly breaks out of the box it should be contained in, I'd think that it's not an actual problem with my program.
The program itself is about 500 lines all in all so I will not post that (also I don't want to share yet). It consists of a small API, a small program that sends stuff over a rednet protocol and the main program which receives the data. This program consists of three threads (input, rednet receive, screen update) that handle term.native() + multiple monitors with individual output.
My main problem here is that I can only reproduce the problem on the server, which is not mine. It restarts once a day and since i don't totally crash the server I only get one shot of testing this a day. Also it's not exactly good sport to crash CC every day. I could narrow it down to about the following scenario:
The program can be quit by pressing "end" on the keyboard or by clicking "X" on any screen. Every block involved is the advanced version. This seems to work when there have been no rednet messages yet. But when I had the sender running (it keeps transmitting when the receiver quits), the crash happenes when I click the "X". It may crash using other means of quitting as well, I could not test that. There is no message, all CC output serverwide just freezes. I'll now try to give an overview what code runs from the moment I click "X":
Input thread captures the click and sets data about the click for another thread to process.
All threads work until shutdown is true, they are started with "parallel.waitForAll(inputThread, updateThread, receiveThread)" so everything shuts down in a controlled way.
The code that determines this click was a click on "X", part of "updateThread":
And then everything just quits their loops after doing their last cycle of work. No data is invalidated or something like that, so there's really no reason anything should crash if it usually runs.
The main program continues with the following after all threads have quit:
As you can see, the first thing that happens is clearing all screens. This does not happen, the crash therefore happens before that. Here are the other two main thread functions for the sake of completion:
I don't know if it makes sense to even look for a problem in the code since it clearly works like a charm in my dev world. It's more to give an idea what features I use.
Thanks for your time. Help me, CC Forum, you're my only hope!
EDIT: I am looking for general weirdness in my program's behavior at the moment (in the test world). One thing I encountered is… What is term.native() anyway? Because it's *not* the original terminal object. I made a test program and on a freshly booted computer this:
behaves differently from this:
The difference is that the command line does not change it's cursor position in the second one and will have the command line overwrite "test". Hence "native()" is not the original object. Maybe that has something to do with the whole thing. I tried redirecting output to "term" itself, that one crashes the computer (it shuts off). I'm guessing that's not really intended behavior, even though I probably should not do that. However, I do not use a single redirect in my program. But I use term.native() like a wrapped monitor.
The problem is, in my dev world everything works great. But on the server, when I do something specific with my program (more later) I crash computercraft for the whole server. The server keeps running though and everything else still works, but all computers/turtles freeze, show the same screen they had when CC crashed and no (fresh) computers I place ever start up.
Now I would be very happy about any pointers as to what I could even do so wrong that this could happen. Since this problem clearly breaks out of the box it should be contained in, I'd think that it's not an actual problem with my program.
The program itself is about 500 lines all in all so I will not post that (also I don't want to share yet). It consists of a small API, a small program that sends stuff over a rednet protocol and the main program which receives the data. This program consists of three threads (input, rednet receive, screen update) that handle term.native() + multiple monitors with individual output.
My main problem here is that I can only reproduce the problem on the server, which is not mine. It restarts once a day and since i don't totally crash the server I only get one shot of testing this a day. Also it's not exactly good sport to crash CC every day. I could narrow it down to about the following scenario:
The program can be quit by pressing "end" on the keyboard or by clicking "X" on any screen. Every block involved is the advanced version. This seems to work when there have been no rednet messages yet. But when I had the sender running (it keeps transmitting when the receiver quits), the crash happenes when I click the "X". It may crash using other means of quitting as well, I could not test that. There is no message, all CC output serverwide just freezes. I'll now try to give an overview what code runs from the moment I click "X":
Input thread captures the click and sets data about the click for another thread to process.
function inputThread()
while shutdown == false do
local a, b, c, d = os.pullEvent()
if a == "key" then
if b == 207 then
shutdown = true
requestUpdate = true
else
--printU(tonumber(c))
end
elseif a == "monitor_touch" then
if click == nil then
click = {}
click["b"] = 2
click["a"] = 1
click["x"] = c
click["y"] = d
click["scr"] = nil
for i in pairs(screen) do
if screen[i]["side"] == b then
click["scr"] = screen[i]
break
end
end
else
click["a"] = click["a"] + 1
end
requestUpdate = true
elseif a == "mouse_click" then
if click == nil then
click = {}
click["a"] = 1
click["b"] = b
click["x"] = c
click["y"] = d
click["scr"] = screen[1]
else
click["a"] = click["a"] + 1
end
requestUpdate = true
end
end
end
All threads work until shutdown is true, they are started with "parallel.waitForAll(inputThread, updateThread, receiveThread)" so everything shuts down in a controlled way.
The code that determines this click was a click on "X", part of "updateThread":
if click ~= nil then
if click["y"] == click["scr"]["h"] then
<code missing>
elseif click["x"] >= 13 and click["x"] <= 15 then
shutdown = true
os.startTimer(1) -- ensure event loop can quit
end
clearS(click["scr"])
end
click = nil
end
And then everything just quits their loops after doing their last cycle of work. No data is invalidated or something like that, so there's really no reason anything should crash if it usually runs.
The main program continues with the following after all threads have quit:
parallel.waitForAll(inputThread, updateThread, receiveThread)
clearU()
nvapi.close()
os.unloadAPI("nvapi")
print("Bla.")
As you can see, the first thing that happens is clearing all screens. This does not happen, the crash therefore happens before that. Here are the other two main thread functions for the sake of completion:
function receiveThread()
while shutdown == false do
sid, msg, prot = rednet.receive(nvapi.protocol, rcvTime)
if msg ~= nil then
acceptMessage(msg)
requestUpdate = true
end
end
end
function updateThread()
while shutdown == false do
while requestUpdate == false do
sleep(0.2)
end
requestUpdate = false
update()
sleep(updTime)
end
end
I don't know if it makes sense to even look for a problem in the code since it clearly works like a charm in my dev world. It's more to give an idea what features I use.
Thanks for your time. Help me, CC Forum, you're my only hope!
EDIT: I am looking for general weirdness in my program's behavior at the moment (in the test world). One thing I encountered is… What is term.native() anyway? Because it's *not* the original terminal object. I made a test program and on a freshly booted computer this:
term.redirect(term.current())
print("test")
sleep(5)
behaves differently from this:
term.redirect(term.native())
print("test")
sleep(5)
The difference is that the command line does not change it's cursor position in the second one and will have the command line overwrite "test". Hence "native()" is not the original object. Maybe that has something to do with the whole thing. I tried redirecting output to "term" itself, that one crashes the computer (it shuts off). I'm guessing that's not really intended behavior, even though I probably should not do that. However, I do not use a single redirect in my program. But I use term.native() like a wrapped monitor.
Edited on 03 January 2015 - 05:37 AM