Ver código fonte

Run commands in separate threads.

tags/v0.1^2
Ben Kurtovic 12 anos atrás
pai
commit
0e2fcfed13
4 arquivos alterados com 31 adições e 24 exclusões
  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 Ver arquivo

@@ -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 Ver arquivo

@@ -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 Ver arquivo

@@ -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 Ver arquivo

@@ -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




Carregando…
Cancelar
Salvar