def get(self): logging.info('started; imp.lock_held:%s', imp.lock_held()) # flush to prove the code started running logservice.flush() with _LOCK: # run a thread which will hold the import lock until we release _LOCK thread = threading.Thread(target=hold_import_lock) thread.start() # wait for the thread to be blocked logging.info('waiting for import lock to be held by thread ...') is_set = _WAITING_FOR_LOCK.wait(30) if not is_set: raise Exception( '_WAITING_FOR_LOCK not set: the module was already imported; this only works on the first call' ) logging.info('done; imp.lock_held:%s', imp.lock_held()) # flush logs: will hang forever due to the call to group.lengthString(...) logservice.flush() logging.info('lock released') thread.join() logging.info('all done') self.response.write('OK!') _WAITING_FOR_LOCK.clear()
def test_waiting_during_different_thread_importing(self): """ EventualResult.wait() should work if called while a module is being imported in a different thread. See EventualResultTests.test_noWaitingDuringImport for the explanation of what should happen if an import is happening in the current thread. """ test_complete = threading.Event() lock_held = threading.Event() er = EventualResult(succeed(123), None) def other_thread(): imp.acquire_lock() lock_held.set() test_complete.wait() imp.release_lock() t = threading.Thread(target=other_thread) t.start() lock_held.wait() # While the imp lock is held by the other thread, we can't # allow exceptions/assertions to happen because trial will # try to do an import causing a deadlock instead of a # failure. We collect all assertion pairs (result, expected), # wait for the import lock to be released, and then check our # assertions at the end of the test. assertions = [] if hasattr(sys, 'pypy_version_info'): # Under PyPy imp.lock_held only returns True if the current thread # holds the lock. If/When that bug is fixed, this assertion # should fail and we should remove this special casing. # See: http://stackoverflow.com/q/23816549/132413 assertions.append((imp.lock_held(), False)) else: # we want to run .wait while the other thread has the lock acquired assertions.append((imp.lock_held(), True)) try: assertions.append((er.wait(), 123)) finally: test_complete.set() assertions.append((imp.lock_held(), True)) test_complete.set() t.join() [self.assertEqual(result, expected) for result, expected in assertions]
def test_manual_locking(self): import thread, os, imp, time, sys f = open(os.path.join(self.tmpdir, 'foobaz2.py'), 'w') f.close() # empty done = [] def f(): sys.path.insert(0, self.tmpdir) import foobaz2 p = sys.path.pop(0) assert p == self.tmpdir done.append(1) assert not imp.lock_held() imp.acquire_lock() assert imp.lock_held() thread.start_new_thread(f, ()) time.sleep(0.9) assert not done assert imp.lock_held() # check that it's a recursive lock imp.acquire_lock() assert imp.lock_held() imp.acquire_lock() assert imp.lock_held() imp.release_lock() assert imp.lock_held() imp.release_lock() assert imp.lock_held() imp.release_lock() assert not imp.lock_held() self.waitfor(lambda: done) assert done
def _load_plugins(self): # Get a list of all plugins... (ignoring any names starting with _) # TODO use a more readable expression like: # [d for d in ... if ...] #self._plugins = dict(map(lambda x: (os.path.basename(x)[:-3], None), glob(plugins.__path__[0] + '/[!_]*.py'))) self._plugins = dict([ (os.path.basename(x)[:-3], None) for x in glob(plugins.__path__[0] + '/[!_]*.py') ]) # and load any that are not yet loaded. # Don't attempt to reload existing ones even if they might have changed, # because I don't know what the consequences be:) try: for plugin in self._plugins.keys(): if not sys.modules.has_key('iobserver.plugins.'+plugin): # Load new plugin imp.acquire_lock() found = imp.find_module(plugin, plugins.__path__) self._plugins[plugin] = imp.load_module('iobserver.plugins.'+plugin, found[0], found[1], found[2]) imp.release_lock() else: # Reload plugin reload(sys.modules['iobserver.plugins.'+plugin]) except Exception, data: if imp.lock_held(): imp.release_lock() if self._thread.isAlive(): iObserverError(self, "Could not load plugin(s): %s" % data) else: raise iObserverError(None, "Could not load plugin(s): %s" % data)
def applog_handle_patched(self, record): ''' Monkey-patch to avoid deadlock in google.appengine.api.app_logging.AppLogsHandler. A rare deadlock is possible because flushing the logs holds this handler's lock, as well as the _LogsDequeBuffer's lock. It then blocks on the import lock as part of the native protocol buffer library for some mysterious reason. Meanwhile, if another thread executes an import that then logs something, it holds the import lock and blocks on the log lock. To avoid it: we try to acquire the log lock. If it fails, we test if import lock is held. If it is, we might deadlock: If this thread holds the import lock, it is not safe to wait for the log lock. Instead, we drop the log message. I did add a task queue message in a previous version, so I know that this does get hit occasionally. For details, see: https://github.com/evanj/app-engine-log-deadlock ''' # Modified from the version in logging.Handler.handle rv = self.filter(record) if rv: # attempt to acquire the lock in a non-blocking fashion to detect deadlocks acquired = self.lock.acquire(False) if not acquired: if imp.lock_held(): # this thread MIGHT hold the import lock (some other thread might also) # it is not safe to block: if we hold the import lock, the thread holding the # log lock will deadlock if it tries to flush return rv # safe to block: this thread does not hold the import lock self.lock.acquire() try: self.emit(record) finally: self.lock.release() return rv
def do(self): if imp.lock_held() is True: # inject global variables instead of rewriting the file self.do_inject() else: # just rewrite self.do_rewrite()
def wait(self, timeout=None): """ Return the result, or throw the exception if result is a failure. It may take an unknown amount of time to return the result, so a timeout option is provided. If the given number of seconds pass with no result, a TimeoutError will be thrown. If a previous call timed out, additional calls to this function will still wait for a result and return it if available. If a result was returned or raised on one call, additional calls will return/raise the same result. """ if threadable.isInIOThread(): raise RuntimeError( "EventualResult.wait() must not be run in the reactor thread.") if imp.lock_held(): # If EventualResult.wait() is run during module import, if the # Twisted code that is being run also imports something the result # will be a deadlock. Even if that is not an issue it would # prevent importing in other threads until the call returns. raise RuntimeError( "EventualResult.wait() must not be run at module import time.") result = self._result(timeout) if isinstance(result, Failure): result.raiseException() return result
def g(*a, **kw): enqueued = curtime() ctx = context.get_context() started = [] def in_thread(*a, **kw): ml.ld3("In thread {0}", f.__name__) started.append(curtime()) return f(*a, **kw) # some modules import things lazily; it is too dangerous # to run a function in another thread if the import lock is # held by the current thread (this happens rarely -- only # if the thread dispatched function is being executed at # the import time of a module) if not ctx.cpu_thread_enabled or imp.lock_held(): ret = in_thread(*a, **kw) elif in_threadpool() is self.pool: ret = in_thread(*a, **kw) else: ctx.stats[self.name + '.depth'].add(1 + len(self.pool)) ret = self.pool.apply_e((Exception,), in_thread, a, kw) ml.ld3("Enqueued to thread {0}/depth {1}", f.__name__, len(pool)) start = started[0] duration = curtime() - start queued = start - enqueued if hasattr(ret, '__len__') and callable(ret.__len__): prsize = ret.__len__() # parameter-or-return size elif a and hasattr(a[0], '__len__') and callable(a[0].__len__): prsize = a[0].__len__() else: prsize = None _queue_stats(name, f.__name__, queued, duration, prsize) return ret
def import_function(pkgmodfunc): steps = pkgmodfunc.split('.') if len(steps) in (0, 1): return None funcname = steps.pop() if not imp.lock_held(): imp.acquire_lock() path = None try: for step in steps: (fil, filename, (suffix, mode, typ)) = imp.find_module(step, path) module = imp.load_module(step, fil, filename, (suffix, mode, typ)) if hasattr(module, '__path__'): path = module.__path__ else: if not hasattr(module, funcname): raise ImportError(pkgmodfunc) try: return getattr(module, funcname) except AttributeError: raise ImportError(pkgmodfunc) finally: imp.release_lock()
def do(self, run=False): if imp.lock_held() is True: # inject global variables instead of rewriting the file self.do_inject() else: # just rewrite self.do_rewrite(run=run)
def __enter__(self): if self.sync or imp.lock_held(): # Some modules like nosetests, coverage etc # python -m unittest test_xxx.py or nosetests test_xxx.py # hang when Python multi-threading was used in the import stage due to (Python # import lock) bug in the threading module. See also # https://github.com/paramiko/paramiko/issues/104 # https://docs.python.org/2/library/threading.html#importing-in-threaded-code # Disable the asynchoronous mode for safe importing def def_async_fn(fn): return fn else: # Enable back-ground mode def def_async_fn(fn): def async_fn(*args, **kwargs): if self.handler is not None: self.handler.join() self.handler = ThreadWithTraceBack(target=fn, args=args, kwargs=kwargs) self.handler.start() return self.handler return async_fn if len(self.fns) == 1: return def_async_fn(self.fns[0]) else: return [def_async_fn(fn) for fn in self.fns]
def load(self, name, notify=True): """ Load a plugin. """ if name in self.plugins: self.unload(name) try: if name in self.modules: imp.acquire_lock() module = imp.reload(self.modules[name]) imp.release_lock() else: file, filename, info = imp.find_module(name, [plugins_dir, default_plugin_path]) imp.acquire_lock() module = imp.load_module(name, file, filename, info) imp.release_lock() except Exception as e: import traceback log.debug("Could not load plugin: \n%s", traceback.format_exc()) self.core.information("Could not load plugin: %s" % e, 'Error') return finally: if imp.lock_held(): imp.release_lock() self.modules[name] = module self.commands[name] = {} self.keys[name] = {} self.tab_keys[name] = {} self.tab_commands[name] = {} self.event_handlers[name] = [] self.plugins[name] = module.Plugin(self, self.core, plugins_conf_dir) if notify: self.core.information('Plugin %s loaded' % name, 'Info')
def run(self, threadrunlimit=None): """ threadrunlimit: only run this many threads at most total, if None (default) then run all threads """ runcount = len(self.threads[self.next_thread:]) if threadrunlimit is not None: runcount = min(runcount, threadrunlimit) next_thread = 0 while runcount > 0: batch = self.threads[next_thread:next_thread + self.maxparallel] # cannot start threads while imp lock is held. toLock = imp.lock_held() if toLock: imp.release_lock() # Start all threads in this batch for thread in batch: thread.start() # Wait for them all to finish for thread in batch: thread.join # rest lock state if toLock: imp.acquire_lock() runcount = runcount - len(batch) next_thread = next_thread + len(batch)
def wait(self, timeout=None): """ Return the result, or throw the exception if result is a failure. It may take an unknown amount of time to return the result, so a timeout option is provided. If the given number of seconds pass with no result, a TimeoutError will be thrown. If a previous call timed out, additional calls to this function will still wait for a result and return it if available. If a result was returned or raised on one call, additional calls will return/raise the same result. """ if imp.lock_held(): try: imp.release_lock() except RuntimeError: # The lock is held by some other thread. We should be safe # to continue. pass else: # If EventualResult.wait() is run during module import, if the # Twisted code that is being run also imports something the result # will be a deadlock. Even if that is not an issue it would # prevent importing in other threads until the call returns. raise RuntimeError( "EventualResult.wait() must not be run at module import time.") try: result = self._result(timeout) except TimeoutError: raise if isinstance(result, Failure): result.raiseException() pass return result
def post_process(self): if self.input == self.output and self.__inputBuffer == self.__outputBuffer: return try: # open file for output (no auto-run) if self.output != '': self.run = False output_file = open(self.output, 'w') # open tmp file else: self.run = True self.output = 'tmp_' + os.path.basename(self.input) output_file = open(self.output, 'w') # write post-processed code to file output_file.write(self.__outputBuffer) finally: output_file.close() # resolve postprocess stage depending on the mode if self.run == False: return else: # if this module is loaded as a library override the import if imp.lock_held() is True: self.override_import() else: self.on_the_fly() # break execution so python doesn't # run the rest of the pre-processed code return
def execute(meth, *args, **kwargs): """ Execute *meth* in a Python thread, blocking the current coroutine/ greenthread until the method completes. The primary use case for this is to wrap an object or module that is not amenable to monkeypatching or any of the other tricks that Eventlet uses to achieve cooperative yielding. With tpool, you can force such objects to cooperate with green threads by sticking them in native threads, at the cost of some overhead. """ setup() # if already in tpool, don't recurse into the tpool # also, call functions directly if we're inside an import lock, because # if meth does any importing (sadly common), it will hang my_thread = threading.currentThread() if my_thread in _threads or imp.lock_held() or _nthreads == 0: return meth(*args, **kwargs) e = event.Event() _reqq.put((e, meth, args, kwargs)) rv = e.wait() if isinstance(rv, tuple) \ and len(rv) == 3 \ and isinstance(rv[1], EXC_CLASSES): (c, e, tb) = rv if not QUIET: traceback.print_exception(c, e, tb) traceback.print_stack() six.reraise(c, e, tb) return rv
def other_thread(): imp.acquire_lock() # 3 assert imp.lock_held() lock_held.release() # 4 test_complete.acquire() # 7 imp.release_lock() # 8 lock_released.release() # 9
def testLock(self): LOOPS = 50 # The import lock may already be held, e.g. if the test suite is run # via "import test.autotest". lock_held_at_start = imp.lock_held() self.verify_lock_state(lock_held_at_start) for i in range(LOOPS): imp.acquire_lock() self.verify_lock_state(True) for i in range(LOOPS): imp.release_lock() # The original state should be restored now. self.verify_lock_state(lock_held_at_start) if not lock_held_at_start: try: imp.release_lock() except RuntimeError: pass else: self.fail("release_lock() without lock should raise " "RuntimeError")
def view_import(name, globals={}, locals={}, fromlist=[], level=0): """the drop-in replacement for __import__, that optionally imports locally as well. """ # don't override nested imports save_import = builtin_mod.__import__ builtin_mod.__import__ = local_import if imp.lock_held(): # this is a side-effect import, don't do it remotely, or even # ignore the local effects return local_import(name, globals, locals, fromlist, level) imp.acquire_lock() if local: mod = local_import(name, globals, locals, fromlist, level) else: raise NotImplementedError("remote-only imports not yet implemented") imp.release_lock() key = name+':'+','.join(fromlist or []) if level <= 0 and key not in modules: modules.add(key) if not quiet: if fromlist: print("importing %s from %s on engine(s)"%(','.join(fromlist), name)) else: print("importing %s on engine(s)"%name) results.append(self.apply_async(remote_import, name, fromlist, level)) # restore override builtin_mod.__import__ = save_import return mod
def check_parallel_module_init(self): if imp.lock_held(): # This triggers on, e.g., from test import autotest. raise unittest.SkipTest("can't run when import lock is held") done = threading.Event() for N in (20, 50) * 3: if verbose: print("Trying", N, "threads ...", end=' ') # Make sure that random and modulefinder get reimported freshly for modname in ['random', 'modulefinder']: try: del sys.modules[modname] except KeyError: pass errors = [] done_tasks = [] done.clear() for i in range(N): t = threading.Thread(target=task, args=(N, done, done_tasks, errors,)) t.start() self.assertTrue(done.wait(60)) self.assertFalse(errors) if verbose: print("OK.")
def post_process(self): try: # set file name if self.output == '': self.output = self.input[0:-len(self.input.split('.')[-1]) - 1] + '_out.' + self.input.split( '.')[-1] # open file for output output_file = io.open(self.output, 'w', encoding=self.writeEncoding) # write post-processed code to file output_file.write(self.__outputBuffer) finally: output_file.close() if self.run: # if this module is loaded as a library override the import if imp.lock_held() is True: self.override_import() else: self.on_the_fly() if not self.save: # remove tmp file if os.path.exists(self.output): os.remove(self.output) if not self.resume: # break execution so python doesn't # run the rest of the pre-processed code sys.exit(0)
def check_parallel_module_init(self): if imp.lock_held(): # This triggers on, e.g., from test import autotest. raise unittest.SkipTest("can't run when import lock is held") done = threading.Event() for N in (20, 50) * 3: if verbose: print("Trying", N, "threads ...", end=' ') # Make sure that random and modulefinder get reimported freshly for modname in ['random', 'modulefinder']: try: del sys.modules[modname] except KeyError: pass errors = [] done_tasks = [] done.clear() for i in range(N): thread.start_new_thread(task, ( N, done, done_tasks, errors, )) done.wait(60) self.assertFalse(errors) if verbose: print("OK.")
def blocking(fullname, requested_type): if utils.is_reactor_thread(): try: raise ImportError( "Cannot import %s: Remote import from reactor thread." % fullname) except: logger.exception( "Cannot import %s: Remote import from reactor thread." % fullname) raise def in_reactor(): d = receiver(fullname, requested_type) return d try: release_count = 0 while imp.lock_held(): release_count += 1 imp.release_lock() return threads.blockingCallFromThread(reactor, in_reactor) finally: while release_count: release_count -= 1 imp.acquire_lock()
def post_process(self): if self.input == self.output and self.__inputBuffer == self.__outputBuffer: return try: # open file for output (no auto-run) if self.output != "": self.run = False output_file = open(self.output, "w") # open tmp file else: self.run = True self.output = "tmp_" + os.path.basename(self.input) output_file = open(self.output, "w") # write post-processed code to file output_file.write(self.__outputBuffer) finally: output_file.close() # resolve postprocess stage depending on the mode if self.run == False: return else: # if this module is loaded as a library override the import if imp.lock_held() is True: self.override_import() else: self.on_the_fly() # break execution so python doesn't # run the rest of the pre-processed code return
def load_module(self, module_name): thread_count = threading.active_count() if thread_count != 1 : while imp.lock_held(): pass imp.acquire_lock() module = sys.modules.setdefault(module_name, imp.new_module(module_name)) if thread_count != 1: imp.release_lock() # not sure when to release; the following doesn't use shared resources (e.g. sys.modules) other than the module itself source, filepath = self.source.pop(module_name) module_code = compile(source, module_name, "exec") is_package = True if len(module_name.split('.')) > 1 else False # not sure, but seems accurate module.__file__ = filepath module.__loader__ = self if is_package: module.__path__ = [] module.__package__ = module_name else: module.__package__ = module_name.split('.', 1)[0] exec module_code in module.__dict__ #imp.release_lock() # it might be more correct to release the lock here instead of above. return module
def wait(self): """ If this isn't the master process, wait for instructions. """ if self.is_master(): return status = MPI.Status() while True: # Event loop. # Sit here and await instructions. if self.debug: print("Worker {0} waiting for task.".format(self.rank)) # Blocking receive to wait for instructions. task = self.comm.bcast(None) if self.debug: print("Worker {0} got task {1}.".format(self.rank, task)) # Check if message is special sentinel signaling end. # If so, stop. if isinstance(task, _close_pool_message): if self.debug: print("Worker {0} close.".format(self.rank)) # Handle global import lock for multithreading, see # http://stackoverflow.com/questions/12389526/import-inside-of-a-python-thread # https://docs.python.org/3.4/library/imp.html#imp.lock_held # Global import lock affects the ctypes module. It leads to deadlock when # ctypes function is called in new threads created by threading module. if sys.version_info < (3, 4): if not imp.lock_held(): imp.acquire_lock() return # Check if message is special type containing new function # to be applied elif isinstance(task, _function_wrapper): code = marshal.loads(task.func_code) if self.debug: print('function {0}'.format(code)) print("Worker {0} replaced its task function: {1}.".format( self.rank, self.function)) self.function = types.FunctionType(code, globals()) else: # message are function args self.worker_status = 'R' ans = self.function(*task) # task = worker_args if isinstance(ans, types.GeneratorType): print( '\nWARNING\n Function {0} returns generator {1}.\n' ' The generator was consumed to avoid workers getting stuck.\n' .format(self.function, ans)) [x for x in ans] ans = x = None self.worker_status = 'P'
def test_lock(self): i=0 while i<5: i+=1 if not imp.lock_held(): self.assertRaises(RuntimeError,imp.release_lock) imp.acquire_lock() else: imp.release_lock()
def CreateRPC(self): """ Create an RPC that can be used asynchronously. """ # If the runtime is importing a module, fall back to the non-threaded RPC. # This prevents a deadlock in cases when the RealRPC thread tries to # acquire the import lock. if imp.lock_held(): return apiproxy_rpc.RPC(stub=self) else: return apiproxy_rpc.RealRPC(stub=self)
def test_lock(): i=0 while i<5: i+=1 if not imp.lock_held(): AssertError(RuntimeError,imp.release_lock) imp.acquire_lock() else: imp.release_lock()
def wait(self): """ If this isn't the master process, wait for instructions. """ if self.is_master(): return status = MPI.Status() while True: # Event loop. # Sit here and await instructions. if self.debug: print("Worker {0} waiting for task.".format(self.rank)) # Blocking receive to wait for instructions. task = self.comm.bcast(None) if self.debug: print("Worker {0} got task {1}.".format(self.rank, task)) # Check if message is special sentinel signaling end. # If so, stop. if isinstance(task, _close_pool_message): if self.debug: print("Worker {0} close.".format(self.rank)) # Handle global import lock for multithreading, see # http://stackoverflow.com/questions/12389526/import-inside-of-a-python-thread # https://docs.python.org/3.4/library/imp.html#imp.lock_held # Global import lock affects the ctypes module. It leads to deadlock when # ctypes function is called in new threads created by threading module. if sys.version_info < (3,4): if not imp.lock_held(): imp.acquire_lock() return # Check if message is special type containing new function # to be applied elif isinstance(task, _function_wrapper): code = marshal.loads(task.func_code) if self.debug: print('function {0}'.format(code)) print("Worker {0} replaced its task function: {1}." .format(self.rank, self.function)) self.function = types.FunctionType(code, globals()) else: # message are function args self.worker_status = 'R' ans = self.function(*task) # task = worker_args if isinstance(ans, types.GeneratorType): print('\nWARNING\n Function {0} returns generator {1}.\n' ' The generator was consumed to avoid workers getting stuck.\n' .format(self.function, ans)) [x for x in ans] ans = x = None self.worker_status = 'P'
def __enter__(self): fns = self.fns handlers = self.handlers ntasks = len(self.fns) global_import_lock = False if sys.version_info < (3, 6): import imp global_import_lock = imp.lock_held() if self.sync or global_import_lock: # Some modules like nosetests, coverage etc # python -m unittest test_xxx.py or nosetests test_xxx.py # hang when Python multi-threading was used in the import stage due to (Python # import lock) bug in the threading module. See also # https://github.com/paramiko/paramiko/issues/104 # https://docs.python.org/2/library/threading.html#importing-in-threaded-code # Disable the asynchoronous mode for safe importing def def_async_fn(i): return fns[i] elif ThreadPoolExecutor is None: # async mode, old python def def_async_fn(i): def async_fn(*args, **kwargs): if self.handlers[i] is not None: self.handlers[i].join() self.handlers[i] = ThreadWithTraceBack(target=fns[i], args=args, kwargs=kwargs) self.handlers[i].start() return self.handlers[i] return async_fn else: # multiple executors in async mode, python 2.7.12 or newer executor = self.executor = ThreadPoolExecutor( max_workers=ntasks) def def_async_fn(i): def async_fn(*args, **kwargs): if handlers[i] is not None: try: handlers[i].result() except Exception as e: raise ThreadRuntimeError( 'Error on thread %s:\n%s' % (self, e)) handlers[i] = executor.submit(fns[i], *args, **kwargs) return handlers[i] return async_fn if len(self.fns) == 1: return def_async_fn(0) else: return [def_async_fn(i) for i in range(ntasks)]
def test_waiting_during_different_thread_importing(self): """ EventualResult.wait() should work if called while a module is being imported in a different thread. See EventualResultTests.test_noWaitingDuringImport for the explanation of what should happen if an import is happening in the current thread. """ test_complete = threading.Event() lock_held = threading.Event() er = EventualResult(succeed(123), None) def other_thread(): imp.acquire_lock() lock_held.set() test_complete.wait() imp.release_lock() t = threading.Thread(target=other_thread) t.start() lock_held.wait() # While the imp lock is held by the other thread, we can't # allow exceptions/assertions to happen because trial will # try to do an import causing a deadlock instead of a # failure. We collect all assertion pairs (result, expected), # wait for the import lock to be released, and then check our # assertions at the end of the test. assertions = [] # we want to run .wait while the other thread has the lock acquired assertions.append((imp.lock_held(), True)) try: assertions.append((er.wait(), 123)) finally: test_complete.set() assertions.append((imp.lock_held(), True)) test_complete.set() t.join() [self.assertEqual(result, expected) for result, expected in assertions]
def g(*a, **kw): ctx = context.get_context() # in_cpubound_thread is sentinel to prevent double-thread dispatch if (not ctx.cpu_thread_enabled or imp.lock_held() or getattr(ctx.thread_locals, 'in_cpubound_thread', False)): return f(*a, **kw) if not hasattr(ctx.thread_locals, 'cpu_bound_thread'): ctx.thread_locals.cpu_bound_thread = CPUThread() ml.ld3("Calling in cpu thread {0}", f.__name__) return ctx.thread_locals.cpu_bound_thread.apply(f, a, kw)
def test_main(): import imp if imp.lock_held(): # If the import lock is held, the threads will hang. raise TestSkipped("can't run when import lock is held") try: testall() finally: cleanup()
def find_module(self, name, path=None): # Simulate some thread-unsafe behaviour. If calls to find_module() # are properly serialized, `x` will end up the same as `numcalls`. # Otherwise not. assert imp.lock_held() with self.lock: self.numcalls += 1 x = self.x time.sleep(0.01) self.x = x + 1
def test_import_lock(self): import thread, imp assert not imp.lock_held() done = [] def f(): print '[ENTER %d]' % i from imghdr import testall print '[LEAVE %d]' % i done.append(1) for i in range(5): print '[RUN %d]' % i thread.start_new_thread(f, ()) self.waitfor(lambda: len(done) == 5) assert len(done) == 5
def test_import_lock(self): # XXX XXX XXX this test fails if run together with all other tests # of this directory, but not when run alone import thread, imp assert not imp.lock_held() done = [] def f(i): print '[ENTER %d]' % i from imghdr import testall print '[LEAVE %d]' % i done.append(1) for i in range(5): print '[RUN %d]' % i thread.start_new_thread(f, (i,)) self.waitfor(lambda: len(done) == 5) assert len(done) == 5
def test_import_lock(self): # XXX XXX XXX this test fails if run together with all other tests # of this directory, but not when run alone import _thread, imp assert not imp.lock_held() done = [] def f(i): print('[ENTER %d]' % i) from imghdr import testall print('[LEAVE %d]' % i) done.append(1) for i in range(5): print('[RUN %d]' % i) _thread.start_new_thread(f, (i,)) self.waitfor(lambda: len(done) == 5) assert len(done) == 5
def test_main(): # magic name! see above global N, done import imp if imp.lock_held(): # This triggers on, e.g., from test import autotest. raise TestSkipped("can't run when import lock is held") done.acquire() for N in (20, 50) * 3: if verbose: print "Trying", N, "threads ...", for i in range(N): thread.start_new_thread(task, ()) done.acquire() if verbose: print "OK."
def execute(meth,*args, **kwargs): """ Execute *meth* in a Python thread, blocking the current coroutine/ greenthread until the method completes. The primary use case for this is to wrap an object or module that is not amenable to monkeypatching or any of the other tricks that Eventlet uses to achieve cooperative yielding. With tpool, you can force such objects to cooperate with green threads by sticking them in native threads, at the cost of some overhead. """ setup() # if already in tpool, don't recurse into the tpool # also, call functions directly if we're inside an import lock, because # if meth does any importing (sadly common), it will hang my_thread = threading.currentThread() if my_thread in _threads or imp.lock_held() or _nthreads == 0: return meth(*args, **kwargs) cur = greenthread.getcurrent() # a mini mixing function to make up for the fact that hash(greenlet) doesn't # have much variability in the lower bits k = hash(cur) k = k + 0x2c865fd + (k >> 5) k = k ^ 0xc84d1b7 ^ (k >> 7) thread_index = k % _nthreads reqq, _thread = _threads[thread_index] e = event.Event() reqq.put((e,meth,args,kwargs)) rv = e.wait() if isinstance(rv,tuple) \ and len(rv) == 3 \ and isinstance(rv[1],EXC_CLASSES): import traceback (c,e,tb) = rv if not QUIET: traceback.print_exception(c,e,tb) traceback.print_stack() raise c,e,tb return rv
def test_lock_held_by_another_thread(self): import thread, imp lock_held = thread.allocate_lock() test_complete = thread.allocate_lock() lock_released = thread.allocate_lock() def other_thread(): imp.acquire_lock() # 3 assert imp.lock_held() lock_held.release() # 4 test_complete.acquire() # 7 imp.release_lock() # 8 lock_released.release() # 9 lock_held.acquire() test_complete.acquire() lock_released.acquire() # thread.start_new_thread(other_thread, ()) # 1 lock_held.acquire() # 2 assert imp.lock_held() # 5 test_complete.release() # 6 lock_released.acquire() # 10
def apply(self, library_name, inputhash, dry_run = False): """ Changes the state of the system according to what the module specified does Keyword arguments: library_name -- the python module to load inputhash -- the list of dictionaries of config for the library dry_run -- whether or not to actually change the system """ log.debug('entering state.apply %s', [library_name, inputhash, dry_run]) if library_name not in sys.modules: try: imp.acquire_lock() mod = imp.find_module(library_name, self.libraries) imp.load_module(library_name, *mod) except ImportError: log.exception("Couldn't find module %s in dirs %s", library_name, self.libraries) raise finally: if imp.lock_held(): imp.release_lock() log.debug('loading library: %s', library_name) library = importlib.import_module(library_name) schema = library.schema() for item in inputhash: jsonschema.validate(item, schema) failed = library.verify(inputhashes=inputhash, log=log) log.debug('dry run: %s', dry_run) if not dry_run: log.debug('applying state...') library.apply(inputhashes=failed, log=log) failed = library.verify(inputhashes=inputhash, log=log) if len(failed) > 0: log.error("Failed for good on {}".format(failed)) log.debug('Leaving state.apply %s', failed) return failed
try: module = imp.load_module(segment, module_file, module_path, module_description) path = getattr(module, '__path__', None) except SyntaxError, e: raise except ImportError,e: raise except Exception, e: if not silent: raise module = None error = e finally: if module_file: module_file.close() if imp.lock_held(): imp.release_lock() return module class GnrException(Exception): """Standard Gnr Exception""" code = 'GNR-001' description = '!!Genro base exception' caption = """!!Error code %(code)s : %(description)s.""" localizer = None def __init__(self, description=None, **kwargs): if description: self.description = description self.msgargs = kwargs self.localizer = None
def verify_lock_state(self, expected): self.assertEqual(imp.lock_held(), expected, "expected imp.lock_held() to be %r" % expected)