An unstoppable script and how to stop it
In a previous article, we have constructed an infinite script in Python. That means the script does not simply stop itself once the execution has been begun. It brings us to a following question:
Is it possible to (manually) stop an infinite script in Python?
The question above leads to another one.
If it is possible, can we develop a script that is harder for users to terminate it?
In this blog post I’ll show you what I have found while looking for the answer for these two questions.
Stopping a script in Python
For the sake of simplicity, let’s introduce a simple infinite script in Python as follows:
# main.py
def infiniteLoop():
while True:
pass
infiniteLoop()
The script can be executed in terminal by the command python3 main.py. Obviously, the script won’t stop itself. One can easily terminate it by hitting the combination Ctrl + C and the generated traceback is shown below:
^CTraceback (most recent call last):
File "main.py", line 6, in <module>
infiniteLoop()
File "main.py", line 4, in infiniteLoop
pass
KeyboardInterrupt
Should we be self-satisfied with a way to terminate a script? Probably not.
Developing an unstoppable script
One thing we can obtain from the traceback is that a KeyboardInterrupt error is raised to terminate the script 1. Therefore we can manage what to do if the error occurs by using a try/except block in the code. A naive attempt is to put another infiniteLoop() in the except block. It goes as follows:
try:
infiniteLoop()
except KeyboardInterrupt:
infiniteLoop()
However, users still be able to terminate the script by hitting Ctrl-C twice. Of course we can handle the error raised when hitting Ctrl-C the second time.
try:
infiniteLoop()
except KeyboardInterrupt:
try:
infiniteLoop()
except KeyboardInterrupt:
infiniteLoop()
Sadly, hitting Ctrl+C thrice is a way to stop the script above. We can append many try/except blocks to increase the complexity of the script but this approach is going nowhere since users can hitting Ctrl+C as many times as they prefer to stop the program.
An idea and its implementation
What we really want is to make the script goes endlessly as follows:
try:
infiniteLoop()
except KeyboardInterrupt:
try:
infiniteLoop()
except KeyboardInterrupt:
try:
infiniteLoop()
except KeyboardInterrupt:
...
Our program must contain a finite number of characters, hence we can not naively implement the idea above. However, there is some kind of repetition here, it suggests us define a function to somehow shift the second try statement (at $4^\text{th}$ line) to the first try statement (at $1^\text{st}$ line). By some logical thinking, I can come up with the code below.
def properInfiniteLoop():
try:
infiniteLoop()
except KeyboardInterrupt:
properInfiniteLoop()
Combining with all previous code snippets, we have the final version the the script. One can not stop the script by hitting Ctrl + C, no matter how many times the combination is used.
# main.py
def infiniteLoop():
while True:
pass
def properInfiniteLoop():
try:
infiniteLoop()
except KeyboardInterrupt:
properInfiniteLoop()
properInfiniteLoop()
I was quite confident about my unstoppable script until I accidentally hit some keystrokes on keyboard …
Other methods to terminate a running script
While working on the this blog post, I accidentally hit the combination Ctrl + \ 2 in terminal (in Ubuntu OS), the line Quit (core dumped) showed and the script stopped. In addition, it is not the only way to stop a process running in the system, Ctrl + Z combination and kill command are two alternative methods, just to name a few of them.
Perhaps there is no way to run a script endlessly without users’ permission. It could be true, just for now.