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

[Solved] [Lua] Help with parallel and [ctrl] + T

Started by darkrising, 05 July 2013 - 06:29 AM
darkrising #1
Posted 05 July 2013 - 08:29 AM
Hello, I'm trying to secure one of my programs from the dreaded [ctrl] + T.

It originally used pcall to stop [ctrl] + T on the read function however in the latest versions of computercraft pcall is not working as it used too.

I have tried to use os.pullEvent = os.pullEventRaw however my program is running in parallel so I get a "parallel: 22 Expected string" error.

I could write a coroutine function myself but I have little understanding (even after reading a tutorial) of how they work.

Any help is much appreciated :)/>

Edit: I also tried making a loop that listens for the [ctrl] key and shuts down straight away, but it proved to be very unreliable.


———————————————-


The fix for this was quite simple.
  1. Declare os.pullEvent = os.pullEventRaw
  2. Make sure all your event driven loops check the event they are driven by!
  3. £££ Profit!
Zudo #2
Posted 05 July 2013 - 12:40 PM
I did this too, I have a script here:

Spoiler


local function create( first, ... )
if first ~= nil then
return coroutine.create(first), create( ... )
	end
	return nil
end

local function runUntilLimit( _routines, _limit )
	local count = #_routines
	local living = count

	local tFilters = {}
	local eventData = {}
	while true do
	 for n=1,count do
	 local r = _routines[n]
	 if r then
	 if tFilters[r] == nil or tFilters[r] == eventData[1] then
	local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param )
else
tFilters[r] = param
end
if coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 end
	 end
for n=1,count do
	 local r = _routines[n]
if r and coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 eventData = { os.pullEventRaw() }
	end
end

function waitForAny( ... )
	local routines = { create( ... ) }
	return runUntilLimit( routines, #routines - 1 )
end

function waitForAll( ... )
	local routines = { create( ... ) }
runUntilLimit( routines, 0 )
end

It is safe against ctrl-t and works the same as the original parallel api
darkrising #3
Posted 05 July 2013 - 01:03 PM
Thank you that looks promising, however something I noticed was by changing the order of the functions passed to the parallel api, [ctrl] + T doesn't have an effect.

I have no idea why.


Edit: Maybe not, on further testing I could not replicate the same outcome
darkrising #4
Posted 05 July 2013 - 01:50 PM
I did this too, I have a script here:

Spoiler


local function create( first, ... )
if first ~= nil then
return coroutine.create(first), create( ... )
	end
	return nil
end

local function runUntilLimit( _routines, _limit )
	local count = #_routines
	local living = count

	local tFilters = {}
	local eventData = {}
	while true do
	 for n=1,count do
	 local r = _routines[n]
	 if r then
	 if tFilters[r] == nil or tFilters[r] == eventData[1] then
	local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param )
else
tFilters[r] = param
end
if coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 end
	 end
for n=1,count do
	 local r = _routines[n]
if r and coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 eventData = { os.pullEventRaw() }
	end
end

function waitForAny( ... )
	local routines = { create( ... ) }
	return runUntilLimit( routines, #routines - 1 )
end

function waitForAll( ... )
	local routines = { create( ... ) }
runUntilLimit( routines, 0 )
end

It is safe against ctrl-t and works the same as the original parallel api

Where does this differ from the parallel api?
Lyqyd #5
Posted 05 July 2013 - 11:24 PM
Please post your code.
darkrising #6
Posted 06 July 2013 - 09:06 AM
Please post your code.

https://raw.github.com/darkrising/darkprograms/darkprograms/darksecurity/client

It's one of my base security programs, I used to use pcall but it seems to be the parallel api that is exiting.
Zudo #7
Posted 06 July 2013 - 11:27 AM
I did this too, I have a script here:

Spoiler


local function create( first, ... )
if first ~= nil then
return coroutine.create(first), create( ... )
	end
	return nil
end

local function runUntilLimit( _routines, _limit )
	local count = #_routines
	local living = count

	local tFilters = {}
	local eventData = {}
	while true do
	 for n=1,count do
	 local r = _routines[n]
	 if r then
	 if tFilters[r] == nil or tFilters[r] == eventData[1] then
	local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param )
else
tFilters[r] = param
end
if coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 end
	 end
for n=1,count do
	 local r = _routines[n]
if r and coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
	 eventData = { os.pullEventRaw() }
	end
end

function waitForAny( ... )
	local routines = { create( ... ) }
	return runUntilLimit( routines, #routines - 1 )
end

function waitForAll( ... )
	local routines = { create( ... ) }
runUntilLimit( routines, 0 )
end

It is safe against ctrl-t and works the same as the original parallel api

Where does this differ from the parallel api?

There is a line, I can't remember where, which was different. I think it waited for an event, and then checked to see if it was the correct event before terminating.
theoriginalbit #8
Posted 06 July 2013 - 11:39 AM
There is a line, I can't remember where, which was different. I think it waited for an event, and then checked to see if it was the correct event before terminating.
Nope, looks identical to the parallel API to me! :P/>
Zudo #9
Posted 06 July 2013 - 12:32 PM
There is a line, I can't remember where, which was different. I think it waited for an event, and then checked to see if it was the correct event before terminating.
Nope, looks identical to the parallel API to me! :P/>

It works for me though!
darkrising #10
Posted 06 July 2013 - 12:54 PM
-snip-

Doesn't work for me, on further testing it seems that it is only when the username and password loop + disk checking loop are running together the program can be [ctrl] + T however when both options are running by themselves the program seems to be quite secure.

I don't know why it is doing this.
Lyqyd #11
Posted 06 July 2013 - 03:49 PM
Line 54 allows it to terminate. When that function receives a terminate event, line 54 will throw an "expected string" error, since you aren't verifying that you're actually getting a disk event.
Zudo #12
Posted 07 July 2013 - 03:53 AM
Line 54 allows it to terminate. When that function receives a terminate event, line 54 will throw an "expected string" error, since you aren't verifying that you're actually getting a disk event.

That is weird, because it has always worked for me.
darkrising #13
Posted 07 July 2013 - 06:30 AM
Line 54 allows it to terminate. When that function receives a terminate event, line 54 will throw an "expected string" error, since you aren't verifying that you're actually getting a disk event.

Thank you very much, the problem is now solved. I didn't realize os.pullEventRaw responds to the terminate event aswell.

A short loop to check the event later and the probem has been solved.

Thank you to all that helped :)/>