To Anyone reading (and samir), Sorry but this one is long and i have spent better part of a day or 2 on this (across 8-10 ish hours). i just dont wanna miss a detail that is crucial, its rather hard to explain since the server is split up (though that may have something to do with why process will get a pointer issue if spawned in async)
Some Notes of why i may be using async incorrectly in some areas
I have spent the last few hours debugging an issue with sockets or the async "base" module, but its not giving me much and i cant seem to attach the debugger for some reason (just does nothing but says its running) i also tried using async correctly and incorrectly, it makes VERY little difference, if i use sleep it causes the apps to lag after running for 20+ mins. closing the ui helps this but it comes back right away, even if i set edit text to "")
Context/What does the server do?
the issue is not consistent, but let me lay some context since the server is spread across 6 modules of my own and is harder to read here (may use github if its not the client being the issue)
- First the server uses the Async socket example (the one with a for loop to handle a table of clients) to connect clients
- Then the server will send a packet to the client for a username though this is ignored for now (was testing around with buffer)
- The server has a chat/Edit window that acts as a console and chat (this makes no difference in my testing) and the clients have the same thing as well, but when the clients get data it just puts it straight into the edit UI rather than console
- if the (server/a client) enters anything it will send to (all clients/server), if the server/any client enters "/c " then anything after the "/c " is sent to the CMD Process (example: /c echo Hello World)
~~ the buggy part i still cant get stable:
- The process's OnRedirect function can be a bit much for the server to parse and send back info to clients if bursts come through (as they often do), SO i have used async around that redirect AND/OR await the Sending of all sockets in a for loop (This works the best)
- The Buggy part is here from what i can tell (but i got the server stable, and can easily cause the issue again on the server): When the client sends "/start", the server will start reading batch commands from a table(Start JVM+30 lines) straight to the CMD (process module), then the Onredirect() fires off packets to the sockets (if i send "blocks" stuff gets dropped out real quick, assuming i dont adjust recv limit for clients)
With Context set about the server here is the issue im getting in greater detail:
The clients Are not remaining alive randomly, Nor do they error or exit in any flow path within my luaRT script (literally just closes), to put it blunty the app crashes at 269 ~ 277 mb OR will just crash upon the first 6 packets from the server. yet i can spam packets from a double nested async for loop (4x the throughput my table commands are being fed into the CMD) without the clients really caring.
It seems the buffers are not being collected or are leaking and causing windows to kill the app (this is not an issue if i can force allocate more ram or have better control of collecting garbage so windows aint freaking out)
The Part that is making me think its a bug is that the clients can then REJOIN to the server after they crash, the cmd process firing off packets from the actual "JVM game server" i launched from the batch command table will work just fine. I even tried making the clients run 2 async loops that did the same thing, it runs farther and handles more but not by much.
The last thing ill add in here is that if the Server doesnt run the "JVM gameserver" (done by moving the exe out of the server folder, the writes still happen) the bug only happens when the lua server starts writing to the process, then redirects get caught and go to clients (keep in mind the server or gameserver does not crash/hang, just the clients).
- Though i will note that if the server writes line by line from the Batch args then the clients can use /start 5 or 6 times without crashing (Still crashes at 269 ~ 277mb though)
Does Async make any notable difference?
Using async or await when sending to the clients has no real effect aside extending the time until crashing or the client just crashs faster. i tried the nagle thing but it yielded no difference. i also tried using collectgarbage("count"), but the tootip is cut off and i cannot find documentation for how to use this in luaRT.
Documentation (Reach out if help is needed)
are there are other functions or app settings within the lua env i can access/set?
i didnt know about collectgarbage function as its not noted anywhere/in search, though running "start" will just make my socket disconnect, so im guessing collectgarbage has a way to "remove" buffers and empty variables that "leak" and cause potential crashes
My Client Code (Can also provide a public github for you to review the server if needbe)
Heres the Current Version of the Client Code, if the server uses line to line writing it runs a bit longer but not stable at all still:
Console = require("console") console = Console
ZIP = require("compression") zip = ZIP
sys = require("sys")
SYSUTIL = require("sysutils") sysutil = SYSUTIL
NET = require("net") net = NET
UI = require("Library/UIV2") ui = UI --switch this to ui if needed, i have a custom print
JSON = require("json") json = JSON
CPU = require("cpu") cpu = CPU
--Convert to console for testing
local win = ui.Window("Chat client", 900, 600, "dialog")
local edit = ui.Edit(win, "", 4, 2, 312, 173)
EWrite= function(Msg, Args) edit:append(tostring(Msg)..'\n', Args) end
edit.font = "Consolas"
edit.fontsize = 9
edit.readonly = true
edit.bgcolor = 0
edit.fgcolor = 0xAAAAAA
edit.wordwrap = true
local entry = ui.Entry(win, "", 3, 176, 313, 22)
function win:onClose()
sys.exit()
end
local client = NET.Socket("26.221.247.83", "9000")
client.blocking = false
async(function()
function entry:onSelect()
edit:append("[You]: "..tostring(entry.text).."\n")
AuthFlag = true
client:send(entry.text)
entry.text = ""
end
end)
function win:onShow()
print("Connecting")
edit:append("This Version of the Client is VERY Basic, Until i write up a Thread manager And/or a proper packet manager; The clients will serve as a Chat/Relay. There is no control yet (Just commands)")
edit:append("Connecting... ")
local Server = await(client:connect()) --need to await here, the server may send the packet to late/soon
if Server then
print("Connected- no Thread")
edit:append("done "..tostring(Server).."!\nConnected to the server !\n")
print("Connected")
async(function()
while true do
-- update user interface
edit.width = win.width-8
edit.height = win.height-27
entry.y = win.height-24
ui.update()
sleep(5)
end
end)
while true do
local msg = await(client:recv()) or NET.error
EWrite(msg, {Src="MSG"})
end
print("Loop Died")
else
error("Network error: failed to connect to the server")
end
--UI.update()
end
win:show()
sys.atexit = function()
print("You are leaving LuaRT !")
end
waitall()
print("THREADS CUT")
sleep(20000)