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

SuperTermination - The Future Of Termination! Implement Today!

Started by cyanisaac, 04 July 2015 - 05:06 AM
cyanisaac #1
Posted 04 July 2015 - 07:06 AM
Termination is sloppy in ComputerCraft. You hold down a key combination for a few seconds and then it plops you right back into the shell with no care as to how it cleans itself up. As well, it can be disabled easily by any program by setting os.pullEvent to os.pullEventRaw.

So it's just that - sloppy, and honestly stupid. But what I'm going to show you today is the future of terminating programs. And I call it superterminate.

Supertermination is using parallel.waitForAny() to run both the foreground (program) process and a background process at the same time. In the background process, you are checking for something to happen and then if that condition is met, you are ending the background process which kills the foreground (program) process.


So why is this better than normal termination?
  • More secure - you can disable superterminate selectively whilst completely disabling normal termination, meaning no unintended side effects from terminating.
  • More robust - you can plug superterminate into anything you want, meaning you can customize how it is done. This allows for using it in robust GUIs.
  • More clean - you can run code to prepare the shell to be terminated, so you don't have to deal with what the program leaves behind.
  • Less buggy - you don't have to worry about superterminate killing its parent process - it will only affect things in the parallel and anything below it on a term of scope.
Apparently this isn't any better than normal termination, forgive me. If you still want the code get it below.


oldPullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw

function backgroundProcess()
  while true do
	if fs.exists("/.terminate") then
	  return
	else
	  sleep(0)
	end
  end
end
function foregroundProcess()
  shell.run("/rom/programs/edit")
end

local currentTerm = term.current()
parallel.waitForAny(backgroundProcess, foregroundProcess)
term.redirect(currentTerm)


The above example is very simple. as soon as .terminate exists in the root directory, the program will terminate. One thing to note is how it backs up the term.current(). This is because several APIs such as textutils (wrongfully) override this and can cause issues. Implementing this will fix issues that can occur with these apis. Another thing to note is the overwriting of os.pullEvent. This is done to disable terminating (since users won't need it because of supertermination) increasing security and decreasing issues. However, always back up overwritten objects, in case you need it later.

Now clearly this code is flawed and not production ready, as it will of course always terminate once the file exists, and won't clean up the shell etc. However, making your superterminate robust is out of the scope of this tutorial as it differs depending on its application.

I hope this tutorial has served you well.

If you would like to see some examples of supertermination implementation in operating systems, both OpenTerminalOS and O[OS] have supertermination implemented. I would recommend poking around their code and seeing how it is done.
Edited on 05 July 2015 - 03:17 PM
flaghacker #2
Posted 04 July 2015 - 01:23 PM
Wait… What? What is supertermination? What's wrong with ctrl+t? You could handle the 'real' terminate event yourself using os.pullEventRaw… How is this a tutorial? Why is 'supertermination' usefull?
Edited on 04 July 2015 - 11:24 AM
biggest yikes #3
Posted 04 July 2015 - 04:21 PM
you could use os.pullEventRaw and check if the user gives a "terminate" event and handle it that way, so your point on "no cleanup" can easily be fixed
even better, your X button in OTOS could just execute

os.queueEvent("terminate")
so that program can handle you exiting it aswell

since you said it would prevent the app from blocking it, that idea is worthless.
Edited on 04 July 2015 - 04:27 PM
cyanisaac #4
Posted 04 July 2015 - 10:50 PM
Wait… What? What is supertermination? What's wrong with ctrl+t? You could handle the 'real' terminate event yourself using os.pullEventRaw… How is this a tutorial? Why is 'supertermination' usefull?

CTRL+T takes a few seconds to register, and can sometimes be buggy. SuperTermination can be triggered instantly. As well, supertermination cannot be disabled by its child process.
Creator #5
Posted 05 July 2015 - 10:10 AM
It never is buggy, it just can be bypassed.
cyanisaac #6
Posted 05 July 2015 - 05:16 PM
It never is buggy, it just can be bypassed.

OpenTerminalOS would get terminated all the way past the bootloader if you were to terminate any program it was running, hence why I implemented the force quit button using supertermination.
Anavrins #7
Posted 05 July 2015 - 05:53 PM
OpenTerminalOS would get terminated all the way past the bootloader if you were to terminate any program it was running.
No it wouldn't, just use pullEventRaw("terminate") so you can control how to close your program, including breaking out of your main loop and letting it end gracefully.
This won't terminate your OS.
Waitdev_ #8
Posted 31 July 2015 - 03:12 PM
yeah, i don't really know how this is supposed to be useful
Creator #9
Posted 31 July 2015 - 08:08 PM
I asked myself the same. A nice way to terminate a process in an OS is: process[id] = nil.