Create a commands.process function which runs a function inside a separate process.

This is the only way to limit the execution time of a possibly long-running python statement.
Use this on String.re, due to the possibility of pathologically long re matching in python.
This allows us to remove the 'trusted-only' restriction on string.re.
In the future, this should probably be used in other places that take user-supplied regexps,
such as 'misc last --regexp', for example, as well as other potentially long-running tasks
that can block the bot.

Conflicts:

	plugins/String/plugin.py
	src/commands.py
This commit is contained in:
Daniel Folkinshteyn 2010-08-05 01:20:46 -04:00 committed by Valentin Lorentz
parent 0d97adadc4
commit 37597bfe94
5 changed files with 32 additions and 1 deletions

View File

@ -33,12 +33,14 @@ import binascii
import supybot.utils as utils
from supybot.commands import *
import supybot.commands as commands
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('String')
import multiprocessing
class String(callbacks.Plugin):
@internationalizeDocstring

View File

@ -988,6 +988,23 @@ class CommandThread(world.SupyThread):
finally:
self.cb.threaded = self.originalThreaded
class CommandProcess(world.SupyProcess):
"""Just does some extra logging and error-recovery for commands that need
to run in processes.
"""
def __init__(self, target=None, args=(), kwargs={}):
self.command = args[0]
self.cb = target.im_self
procName = 'Process #%s (for %s.%s)' % (world.processesSpawned,
self.cb.name(),
self.command)
log.debug('Spawning process %s (args: %r)', procName, args)
self.__parent = super(CommandProcess, self)
self.__parent.__init__(target=target, name=procName,
args=args, kwargs=kwargs)
def run(self):
self.__parent.run()
class CanonicalString(registry.NormalizedString):
def normalize(self, s):

View File

@ -37,6 +37,8 @@ import types
import getopt
import inspect
import threading
import multiprocessing #python2.6 or later!
import Queue
import supybot.log as log
import supybot.conf as conf

View File

@ -1,3 +1,3 @@
"""stick the various versioning attributes in here, so we only have to change
them once."""
version = '0.83.4.1+limnoria (2011-08-13T01:59:18+0200)'
version = '0.83.4.1+limnoria (2011-08-15T17:24:33+0200)'

View File

@ -37,6 +37,7 @@ import sys
import time
import atexit
import threading
import multiprocessing # python 2.6 and later!
if sys.version_info >= (2, 5, 0):
import re as sre
@ -67,6 +68,15 @@ class SupyThread(threading.Thread):
super(SupyThread, self).__init__(*args, **kwargs)
log.debug('Spawning thread %q.', self.getName())
processesSpawned = 1 # Starts at one for the initial process.
class SupyProcess(multiprocessing.Process):
def __init__(self, *args, **kwargs):
global processesSpawned
processesSpawned += 1
super(SupyProcess, self).__init__(*args, **kwargs)
log.debug('Spawning process %q.', self.name)
commandsProcessed = 0
ircs = [] # A list of all the IRCs.