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.