Skewed Callback - Using KeyboardInterrupt

I am currently repeating a task in a for loop inside a callback using Twisted, but would like the reactor to interrupt the loop in the callback (one) if the user issues KeyboardInterrupt via Ctrl-C. From what I checked, the reactor stops or processes interrupts at the end of the callback.

Is there a way to send KeyboardInterrupt to a callback or an error handler in the middle of a callback run?

Greetings

Chris

#!/usr/bin/env python from twisted.internet import reactor, defer def one(result): print "Start one()" for i in xrange(10000): print i print "End one()" reactor.stop() def oneErrorHandler(failure): print failure print "INTERRUPTING one()" reactor.stop() if __name__ == '__main__': d = defer.Deferred() d.addCallback(one) d.addErrback(oneErrorHandler) reactor.callLater(1, d.callback, 'result') print "STARTING REACTOR..." try: reactor.run() except KeyboardInterrupt: print "Interrupted by keyboard. Exiting." reactor.stop() 
+3
source share
2 answers

It is intentional to avoid (semi) premutation since Twisted is a collaborative multitasking system. Ctrl-C is processed in Python using the SIGINT handler set by the interpreter at startup. The handler sets the flag when it is called. After each byte code is executed, the interpreter checks the flag. If it is installed, KeyboardInterrupt will be raised at that point.

The reactor has its own SIGINT processor. This replaces the behavior of the interpreter handler. The reactor handler initiates a shutdown of the reactor. Since it does not throw an exception, it does not interrupt any code. The loop (or something else) ends, and when control returns to the reactor, it stops.

If you want Ctrl-C (i.e. SIGINT) to raise KeyboardInterrupt, you can simply restore the Python SIGINT handler using the signal module:

 signal.signal(signal.SIGINT, signal.default_int_handler) 

Note, however, that if you send SIGINT while the code is running from Twisted, and not from your own application code, the behavior is undefined because Twisted does not expect a KeyboardInterrupt interrupt.

+6
source

I have this working dandy. Running SIGINT sets a flag for any running task in my code and additionally calls the .callFromThread reactor (reactor.stop) to stop any twisted code:

 #!/usr/bin/env python import sys import twisted import re from twisted.internet import reactor, defer, task import signal def one(result, token): print "Start one()" for i in xrange(1000): print i if token.running is False: raise KeyboardInterrupt() #reactor.callFromThread(reactor.stop) # this doesn't work print "End one()" def oneErrorHandler(failure): print "INTERRUPTING one(): Unkown Exception" import traceback print traceback.format_exc() reactor.stop() def oneKeyboardInterruptHandler(failure): failure.trap(KeyboardInterrupt) print "INTERRUPTING one(): KeyboardInterrupt" reactor.stop() def repeatingTask(token): d = defer.Deferred() d.addCallback(one, token) d.addErrback(oneKeyboardInterruptHandler) d.addErrback(oneErrorHandler) d.callback('result') class Token(object): def __init__(self): self.running = True def sayBye(): print "bye bye." if __name__ == '__main__': token = Token() def customHandler(signum, stackframe): print "Got signal: %s" % signum token.running = False # to stop my code reactor.callFromThread(reactor.stop) # to stop twisted code when in the reactor loop signal.signal(signal.SIGINT, customHandler) t2 = task.LoopingCall(reactor.callLater, 0, repeatingTask, token) t2.start(5) reactor.addSystemEventTrigger('during', 'shutdown', sayBye) print "STARTING REACTOR..." reactor.run() 
+8
source

Source: https://habr.com/ru/post/959190/


All Articles