Reaktor bengkok dihentikan, tetapi program tidak berakhir?

Jadi saya sedang menulis skrip kecil untuk digunakan dengan Deluge. Deluge menggunakan Twisted, dan saya benar-benar tidak begitu paham cara kerjanya. Biasanya saya hanya mencari info lebih lanjut tentangnya, namun memulai dengan Twisted akan memakan waktu lama dan berada di luar cakupan proyek kecil ini. Jadi kupikir aku akan bertanya di sini saja.

Sekarang, saya punya kode ini. Saya akan mencoba menjelaskan bagian-bagian tertentu yang memerlukan bantuan

import base64

import processargs

from deluge.ui.client import client
from twisted.internet import reactor

from deluge.log import setupLogger
setupLogger()

options = processargs.readConfig(os.path.expanduser("~/.deluge-automator"))

d = client.connect(
    host=options['host'],
    port=int(options['port']),
    username=options['username'],
    password=options['password']
)

def start():
    #other code

    t = client.core.add_torrent_file(tfile,
                                     base64.encodestring(data), None)

    t.addCallback(on_torrent_added_success, tfile)
    t.addErrback(on_torrent_added_fail)


def handle_stop_signal(SIGNAL, stack):
    client.disconnect()
    reactor.stop()


def on_torrent_added_success(result, tfile):
    #other code
    start()


def on_torrent_added_fail(result):
    print "Add torrent failed!"
    print "result: ", result


def on_connect_success(result):
    #other code
    start()


d.addCallback(on_connect_success)


def on_connect_fail(result):
    print "Connection failed!"
    print "result: ", result


d.addErrback(on_connect_fail)

signal.signal(signal.SIGTERM, handle_stop_signal)
signal.signal(signal.SIGINT, handle_stop_signal)

reactor.run()

Ketika torrent berhasil ditambahkan, ia harus kembali ke start(), dan memang demikian, tapi menurut saya ia kehilangan reaktor atau semacamnya. Karena sekarang setiap kali ia menerima SIGTERM atau SIGINT, reaktor akan menutup, namun tidak menghentikan program:

± % python2 main.py
Connection was successful!
result:  10
^C^CConnection failed!
result:  [Failure instance: Traceback: <class 'twisted.internet.error.ReactorNotRunning'>: Can't stop reactor that isn't running.
/usr/lib/python2.7/site-packages/twisted/internet/defer.py:551:_runCallbacks
/usr/lib/python2.7/site-packages/deluge/ui/client.py:412:__on_login
/usr/lib/python2.7/site-packages/twisted/internet/defer.py:368:callback
/usr/lib/python2.7/site-packages/twisted/internet/defer.py:464:_startRunCallbacks
--- <exception caught here> ---
/usr/lib/python2.7/site-packages/twisted/internet/defer.py:551:_runCallbacks
main.py:70:on_connect_success
main.py:32:start
main.py:49:handle_stop_signal
/usr/lib/python2.7/site-packages/twisted/internet/base.py:577:stop
]

Jadi reaktornya dihentikan, tapi tidak menghentikan programnya. Saya harus menginterupsi keyboard dua kali. Sekali untuk menghentikan reaktor, dan kedua kalinya untuk melakukan kesalahan. Apakah ada cara tertentu untuk mengatur loop seperti ini?


person mrobinson7627    schedule 20.11.2012    source sumber


Jawaban (1)


reaktor menangani sigint, sigterm itu sendiri (mungkin ada parameter reactor.run() yang menonaktifkannya). Instal reactor.addSystemEventTrigger('before', 'shutdown', client.disconnect) sebagai gantinya.

Lihat twisted: catch keyboardinterrupt dan shutdown dengan benar.

person jfs    schedule 20.11.2012
comment
Hanya ingin menambahkan bahwa tidak aman memanggil Twisted API di dalam pengendali sinyal. Penangan sinyal adalah suatu bentuk pengalihan konteks preemptif, mereka sama tidak amannya dengan thread dan harus ditangani dengan hati-hati. Hanya Twisted API yang ditandai sebagai thread-safe yang dapat digunakan dalam pengendali sinyal (yang paling menarik adalah reactor.callFromThread). - person Jean-Paul Calderone; 21.11.2012