diff --git a/earwigbot/bot.py b/earwigbot/bot.py index c1e8074..8e134d5 100644 --- a/earwigbot/bot.py +++ b/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() diff --git a/earwigbot/commands/threads.py b/earwigbot/commands/threads.py index 97a9738..f434ebf 100644 --- a/earwigbot/commands/threads.py +++ b/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) diff --git a/earwigbot/irc/connection.py b/earwigbot/irc/connection.py index 740292f..2db8e81 100644 --- a/earwigbot/irc/connection.py +++ b/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 diff --git a/earwigbot/managers.py b/earwigbot/managers.py index 975fe62..c3b0c58 100644 --- a/earwigbot/managers.py +++ b/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