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

Event related issue?

Started by Timendainum, 06 December 2013 - 09:37 AM
Timendainum #1
Posted 06 December 2013 - 10:37 AM
I'm pretty new to LUA and I haven't quite explored all of the event handling as of yet and I've run into a problem that I believe is event based. I hoping that somone can point me in the right direction. I *think* I know what's going on (sort of), but I have not come up with a workaround yet.

What I'm working on is a wireless peripheral API using LyqydNet. I have a basic working version and I'm now working on adding in support for OpenCCSensors.

OpenCCSensors uses a custom API called sensor to handle the wrap and call overrides for the peripheral API. What I believe they are doing is calling a Java method in the background and using CC's event handling to capture the result.

I am calling this call() function from a LyqydNet daemon, which is being called by a coroutine.resume(daemonTable.netd, id, msg) call. Which as I understand is the result of a handled event.

When I call the sensor.call() function my daemon never returns the result. Does not output any errors (because it's a background process).

When I put the same code into a foreground running program everything works perfectly, and I get results as expected.

So…. what I think is going on here is that because CC is already handling an event, I think it is unable to handle another event? It seems to me in all the reading I've done I've read something to do with limitations regarding this.

I don't think code is required to solve this, but I'll supply some just to make sure:
Here is the section that matters:

if peripheral.getType(tMessage[2]) == "sensor" then
debug.log(40, "Processing sensor call..")
local tResult = {sensor.call(tMessage[2], tMessage[3], unpack(tArgs))}
debug.log(40, "Sending result..")
safeSend(conn, "data", unpack(tResult))
else
debug.log(40, "Processing peripheral call..")
safeSend(conn, "data", peripheral.call(tMessage[2], tMessage[3], unpack(tArgs)))
end

This is the point at which I'm splitting logic for sensor peripherals and others. As you can see I'm calling the API, and capturing the results. I do have some wrapper function in here like safeSend() and debug.log() but these are not the source of the errors. You can see the source for both on my GitHub repository.

So, like I explained, I think there is a collision problem with the events. So what I tried doing was executing a proxy program. The idea was, let the event launch a new program, the event should then complete, and then the proxy program should execute, thereby bypassing the 2 events at one time problem. But in reality this is not how CC is dealing with it. It is still hanging at the server call.

The proxy program looks like:

--shell.run("opt/nperiOCSproxy", conn, tMessage[2], tMessage[3], unpack(tArgs))
debug.log(30, "nperiOCSproxy called: ", ...)

local args = {...}
local conn = args[1]
local side = args[2]
local method = args[3]
local tArgs = args[4]

debug.log(40, "Calling sensor.call(", side, ",", method, ", args: ", tArgs)
local tResult = {sensor.call(side, method, unpack(tArgs))}
debug.log(40, "Sensor call complete.")

--safeSend(conn, "data", unpack(tResult))
if nperi.connections[conn] then
	debug.log(50, "Sending data; conn: ", conn, " args: ", tResult)
	nets.send(conn, "data", unpack(tResult))
else
	debug.log(1, "No connection to send!")
end

My current thought, and the next thing I'm going to try is to put a sleep() in this program. I'm thinking that is what is happening is that during the event call it never yields control after calling the proxy program. So the event handling the LyqydNet call never get's a chance to complete.

In any case. What I'm looking for here is validation that I've even on the right path. Or is something else going on here that I have no idea about. Either way, how can I work around this?

Source:
nperi API
https://github.com/T...t/lib/nperi.lua

debug API
https://github.com/T...t/lib/debug.lua

nets API
https://github.com/T...pt/lib/nets.lua

nperi daemon
https://github.com/T...vers/nperid.lua

proxy:
https://github.com/Timendainum/Wintermute/blob/master/opt/nperiOCSproxy.lua

Thank you!
Edited on 06 December 2013 - 09:42 AM
Lyqyd #2
Posted 06 December 2013 - 12:40 PM
Hey. I've seen this. I will read through the code and give help a bit later. The root of the issue is likely to be the fact that nothing is resuming the daemon when the event comes in. You'll likely have to use a foreground process to pick up the ocs_response events as well, but I'll see if there's a way around it when I have a few extra minutes.
Timendainum #3
Posted 06 December 2013 - 02:37 PM
Thank you very much Lyqyd. The current code I have on github is trying to use a separate program as a proxy to call the sensor.call() function. I was looking for workarounds, The direct call is still in the code but commented. You will be able to see what I'm up to there.

But just calling os.run or shell.run doesn't seem to replicate just running the program as a foreground process.

I was considering running a foreground process that would recieve the event from OCS, but I wasn't sure that I wasn't going to end up in the same boat as a foreground server would also be event driven, so without actually writing it I wasn't sure it would be worth the effort.

Any thoughts are much appreciated.


UPDATE:

I've created a foreground version of the server and it does work.

https://github.com/Timendainum/Wintermute/blob/master/opt/servers/nperis.lua

I would still prefer to run this as a background process, so if you can think of anything let me know. Thanks!
Edited on 06 December 2013 - 07:08 PM
Lyqyd #4
Posted 08 December 2013 - 01:33 PM
Unfortunately, the way LyqydNet runs things as background processes ends up creating "orphan" coroutines that are outside of the usual event distribution system, and *only* receive incoming packets. I've been working on some pretty major overhauls of LyqydNet, and one of the things I've been working towards is eventual integration into LyqydOS. Once that integration is complete, that would provide a system wherein background servers can be run on computers with both LyqydOS and LyqydNet and still receive other events (since the main coroutine manager would be under my control, it's easier to ensure that event distribution is done correctly without needing to use a foreground server). Please note that there are some major breaking changes coming in the new version, so updating to it will require reworking many programs. It's not ready for primetime yet, but you can see the upcoming changes on my github, if you look at the develop branch of the repository.