2016-08-03 8 views
1

У меня возникли проблемы с запуском многопоточных задач с использованием python RQ (проверено на v0.5.6 и v0.6.0).RQ Таймаут не убивает многопоточные задания

Рассмотрим следующий фрагмент кода, как упрощенная версия того, что я пытаюсь достичь:

thing.py
from threading import Thread 

class MyThing(object): 
    def say_hello(self): 
     while True: 
      print "Hello World" 

    def hello_task(self): 
     t = Thread(target=self.say_hello) 
     t.daemon = True # seems like it makes no difference 
     t.start() 
     t.join() 

main.py
from rq import Queue 
from redis import Redis 
from thing import MyThing 

conn = Redis() 

q = Queue(connection=conn) 

q.enqueue(MyThing().say_hello, timeout=5) 

При выполнении main.py (в то время как rqworker работает в фоновом режиме), работа прерывается, как ожидалось, таймаутом в течение 5 секунд.

Проблема заключается в том, что когда я устанавливаю задачу, содержащую thread/s, такую ​​как MyThing().hello_task, поток работает вечно, и ничего не происходит, когда 5-секундный тайм-аут завершен.

Как запустить многопоточную задачу с RQ, чтобы тайм-аут убьет задачу, ее сыновей, внуков и их жен?

+1

звучит как хороший вопрос к сообщению как RQ вопрос: https: // GitHub .com/nvie/rq/issues – ErikR

+0

Хотелось убедиться, что я ничего не пропустил (?) – Kludge

ответ

1

Когда вы запускаете t.join(), потоки блоков hello_task ожидают, пока поток say_hello не вернется - таким образом, он не получит сигнал таймаута из rq. Вы можете разрешить основному потоку запускать и правильно принимать сигнал таймаута, используя Thread.join с установленным количеством времени ожидания, ожидая завершения потока. Как так:

def hello_task(self): 
    t = Thread(target=self.say_hello) 
    t.start() 
    while t.isAlive(): 
     t.join(1) # Block for 1 second 

Таким образом, вы можете также поймать исключение тайм-аута и обработать его, если вы хотите:

def hello_task(self): 
    t = Thread(target=self.say_hello) 
    t.start() 
    try: 
     while t.isAlive(): 
      t.join(1) # Block for 1 second 
    except JobTimeoutException: # From rq.timeouts.JobTimeoutException 
     print "Thread killed due to timeout" 
     raise