소스 검색

Run commands in separate threads.

tags/v0.1^2
Ben Kurtovic 12 년 전
부모
커밋
0e2fcfed13
4개의 변경된 파일31개의 추가작업 그리고 24개의 파일을 삭제
  1. +15
    -14
      earwigbot/bot.py
  2. +7
    -6
      earwigbot/commands/threads.py
  3. +3
    -3
      earwigbot/irc/connection.py
  4. +6
    -1
      earwigbot/managers.py

+ 15
- 14
earwigbot/bot.py 파일 보기

@@ -124,20 +124,21 @@ class Bot(object):
if self.watcher:
self.watcher.stop(msg)

def _stop_task_threads(self):
"""Notify the user of which task threads are going to be killed.

Unfortunately, there is no method right now of stopping task threads
safely. This is because there is no way to tell them to stop like the
IRC components can be told; furthermore, they are run as daemons, and
daemon threads automatically stop without calling any __exit__ or
try/finally code when all non-daemon threads stop. They were originally
implemented as regular non-daemon threads, but this meant there was no
way to completely stop the bot if tasks were running, because all other
threads would exit and threading would absorb KeyboardInterrupts.
def _stop_daemon_threads(self):
"""Notify the user of which threads are going to be killed.

Unfortunately, there is no method right now of stopping command and
task threads safely. This is because there is no way to tell them to
stop like the IRC components can be told; furthermore, they are run as
daemons, and daemon threads automatically stop without calling any
__exit__ or try/finally code when all non-daemon threads stop. They
were originally implemented as regular non-daemon threads, but this
meant there was no way to completely stop the bot if tasks were
running, because all other threads would exit and threading would
absorb KeyboardInterrupts.

The advantage of this is that stopping the bot is truly guarenteed to
*stop* the bot, while the disadvantage is that the tasks are given no
*stop* the bot, while the disadvantage is that the threads are given no
advance warning of their forced shutdown.
"""
tasks = []
@@ -146,7 +147,7 @@ class Bot(object):
if thread.name not in non_tasks and thread.is_alive():
tasks.append(thread.name)
if tasks:
log = "The following tasks will be killed: {0}"
log = "The following commands or tasks will be killed: {0}"
self.logger.warn(log.format(" ".join(tasks)))

def run(self):
@@ -200,4 +201,4 @@ class Bot(object):
with self.component_lock:
self._stop_irc_components(msg)
self._keep_looping = False
self._stop_task_threads()
self._stop_daemon_threads()

+ 7
- 6
earwigbot/commands/threads.py 파일 보기

@@ -67,7 +67,7 @@ class Threads(Command):
threads = threading.enumerate()

normal_threads = []
task_threads = []
daemon_threads = []

for thread in threads:
tname = thread.name
@@ -84,14 +84,15 @@ class Threads(Command):
else:
tname, start_time = re.findall("^(.*?) \((.*?)\)$", tname)[0]
t = "\x0302{0}\x0301 (id {1}, since {2})"
task_threads.append(t.format(tname, thread.ident, start_time))
daemon_threads.append(t.format(tname, thread.ident,
start_time))

if task_threads:
msg = "\x02{0}\x0F threads active: {1}, and \x02{2}\x0F task threads: {3}."
if daemon_threads:
msg = "\x02{0}\x0F threads active: {1}, and \x02{2}\x0F command/task threads: {3}."
msg = msg.format(len(threads), ', '.join(normal_threads),
len(task_threads), ', '.join(task_threads))
len(daemon_threads), ', '.join(daemon_threads))
else:
msg = "\x02{0}\x0F threads active: {1}, and \x020\x0F task threads."
msg = "\x02{0}\x0F threads active: {1}, and \x020\x0F command/task threads."
msg = msg.format(len(threads), ', '.join(normal_threads))

self.reply(self.data, msg)


+ 3
- 3
earwigbot/irc/connection.py 파일 보기

@@ -93,7 +93,7 @@ class IRCConnection(object):
"""Default process hooks for lines received on IRC."""
self._last_recv = time()
if line[0] == "PING": # If we are pinged, pong back
self.pong(line[1])
self.pong(line[1][1:])

@property
def host(self):
@@ -195,9 +195,9 @@ class IRCConnection(object):
def keep_alive(self):
"""Ensure that we stay connected, stopping if the connection breaks."""
now = time()
if now - self._last_recv > 60:
if now - self._last_recv > 120:
if self._last_ping < self._last_recv:
log = "Last message was received over 60 seconds ago. Pinging."
log = "Last message was received over 120 seconds ago. Pinging."
self.logger.debug(log)
self.ping(self.host)
self._last_ping = now


+ 6
- 1
earwigbot/managers.py 파일 보기

@@ -170,7 +170,12 @@ class CommandManager(_ResourceManager):
"""Respond to a hook type and a :py:class:`Data` object."""
for command in self:
if hook in command.hooks and self._wrap_check(command, data):
self._wrap_process(command, data)
thread = Thread(target=self._wrap_process,
args=(command, data))
start_time = strftime("%b %d %H:%M:%S")
thread.name = "irc:{0} ({1})".format(command.name, start_time)
thread.daemon = True
thread.start()
return




불러오는 중...
취소
저장