Reputation: 23
I change a global variable in a signal handler and poll for it in the main program. But the value does not change in the main thread.
Is there a qualifier that I need to use to make it a volatile (like in Java) variable?
Here's the program:
test.py
import time
import signal
def debug():
closeSession = False
def sigint_handler(signal, frame):
global closeSession
print('Breaking the poll...')
closeSession=True
signal.signal(signal.SIGINT, sigint_handler)
# Start a program...
while not closeSession:
time.sleep(1)
print('Polling... closeSession = %r' % closeSession)
print('Exiting! Bye.')
# Sent 'quit' to stdin of the program
if __name__ == "__main__":
debug()
sigint_handler()
gets called whenever I press Ctrl + C but the new value of closeSession
is not used in the main thread.
I get the following output:
$ python test.py
Polling... closeSession = False
Polling... closeSession = False
I press Ctrl + C
^CBreaking the poll...
Polling... closeSession = False
Press Ctrl + C, again
^CBreaking the poll...
Polling... closeSession = False
Press Ctrl + C, again
^CBreaking the poll...
Polling... closeSession = False
Polling... closeSession = False
Upvotes: 2
Views: 1870
Reputation: 1789
The problem is scope.
Inside the debug()
function, you didn't declare closeSession
as a global, which means that you have two variables called closeSession
. One global and one scoped within the debug()
function. And inside the sigint_handler()
function, you've explicitly instructed to use global one, which is shadowed by the scoped one in the outer function.
You can solve this by declaring global before assignment in debug()
:
def debug():
global closeSession
closeSession = False
...
By the way, your code does not work on windows, it throws a IOError because the sleep function is interrupted. A workaround that worked for me is:
...
while not closeSession:
try:
time.sleep(1)
except IOError:
pass
print('Polling... closeSession = %r' % closeSession)
...
It's not pretty but it works.
Upvotes: 3
Reputation: 3199
You have to set global closeSession
before accessing the variable, else you're creating a local variable with the same name and the loop will never end.
Try this:
import time
import signal
def debug():
global closeSession # <-- this was missing
closeSession = False
def sigint_handler(signal, frame):
global closeSession
print('Breaking the poll...')
closeSession=True
signal.signal(signal.SIGINT, sigint_handler)
# Start a program...
while not closeSession:
time.sleep(1)
print('Polling... closeSession = %r' % closeSession)
print('Exiting! Bye.')
# Sent 'quit' to stdin of the program
if __name__ == "__main__":
debug()
Upvotes: 1