7

My while loop does not exit when Ctrl+C is pressed. It seemingly ignores my KeyboardInterrupt exception. The loop portion looks like this:

while True:
  try:
    if subprocess_cnt <= max_subprocess:
      try:
        notifier.process_events()
        if notifier.check_events():
          notifier.read_events()
      except KeyboardInterrupt:
        notifier.stop()
        break
    else:
      pass
  except (KeyboardInterrupt, SystemExit):
    print '\nkeyboardinterrupt found!'
    print '\n...Program Stopped Manually!'
    raise

Again, I'm not sure what the problem is but my terminal never even prints the two print alerts I have in my exception. Can someone help me figure this problem out?

3
  • 2
    Your first except KeyboardInterrupt catches the exception. It won't be visible to the second except (KeyboardInterrupt, SystemExit) if you don't re-raise it. Commented Dec 27, 2011 at 14:23
  • @eumiro - I commented out the first KeyboardInterrupt and replaced the contents of the exception with 'pass' but I'm still experiencing the same problem. Ctrl+C is being ignored (ps aux shows the process still running as well) Commented Dec 27, 2011 at 14:30
  • @eumiro I've also tried to re-raise the KeyboardInterrupt exception by adding raise KeyboardInterrupt() within the first except KeyboardInterrupt: however I'm still experiencing the same issue. Commented Dec 27, 2011 at 14:50

1 Answer 1

15

Replace your break statement with a raise statement, like below:

while True:
  try:
    if subprocess_cnt <= max_subprocess:
      try:
        notifier.process_events()
        if notifier.check_events():
          notifier.read_events()
      except KeyboardInterrupt:
        notifier.stop()
        print 'KeyboardInterrupt caught'
        raise  # the exception is re-raised to be caught by the outer try block
    else:
      pass
  except (KeyboardInterrupt, SystemExit):
    print '\nkeyboardinterrupt caught (again)'
    print '\n...Program Stopped Manually!'
    raise

The two print statements in the except blocks should execute with '(again)' appearing second.

Sign up to request clarification or add additional context in comments.

9 Comments

While you didn't ask about this, the pass statement in your code creates what is called a spin-lock. Spin-locks consume CPU needlessly and can impact performance of the overall system. There are ways to avoid them. Investigate using Queue.Queue objects for communicating between threads, and select.select or the multiprocessing module for communicating between processes.
So, it occurs to me that my main problem (I thought to be unrelated) is I have forked my script twice to 'daemonize' it. That being the case, KeyboardInterrupt's no longer are connected to the same terminal (however, my script will still print outputs to the active terminal). Is there a way to still utilize KeyboardInterrupt (or another way to end my script manually) within a daemonized program?
currently I have been searching for the processid within the ps aux output and executing a sudo kill [pid]; however, this does not gracefully clean up my code before killing it. I need to close database connections and remove inotify watches before killing the program.
If you're calling os.fork directly, or if the API you use gives you the child process' pid, then you can os.kill(childpid, signal.SIGTERM) explicitly within your except (KeyboardInterrupt) block. That will have the effect of "passing" the control-C to the child process.
But if it's a true daemon process, that means the parent has exited leaving it to run on its own, and you will have to use a "pid file", i.e. the daemon writes its own pid to a file in a known location. A shell script could then kill -TERM `cat $PIDFILE` to terminate the daemon process.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.