X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/7382b7a2d35e93944ff364d36017f51e9a1cd392..6fe8e52020d421797306e5c6536afbcee761510a:/services/fuse/tests/integration_test.py?ds=inline diff --git a/services/fuse/tests/integration_test.py b/services/fuse/tests/integration_test.py index c70593488e..3c11fa2920 100644 --- a/services/fuse/tests/integration_test.py +++ b/services/fuse/tests/integration_test.py @@ -1,9 +1,14 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + import arvados import arvados_fuse import arvados_fuse.command import atexit import functools import inspect +import logging import multiprocessing import os import run_test_server @@ -12,12 +17,8 @@ import sys import tempfile import unittest -_pool = None - - @atexit.register def _pool_cleanup(): - global _pool if _pool is None: return _pool.close() @@ -31,6 +32,17 @@ def wrap_static_test_method(modName, clsName, funcName, args, kwargs): Test().runTest(*args, **kwargs) +# To avoid Python's threading+multiprocessing=deadlock problems, we +# use a single global pool with maxtasksperchild=None for the entire +# test suite. +_pool = None +def workerPool(): + global _pool + if _pool is None: + _pool = multiprocessing.Pool(processes=1, maxtasksperchild=None) + return _pool + + class IntegrationTest(unittest.TestCase): def pool_test(self, *args, **kwargs): """Run a static method as a unit test, in a different process. @@ -38,13 +50,10 @@ class IntegrationTest(unittest.TestCase): If called by method 'foobar', the static method '_foobar' of the same class will be called in the other process. """ - global _pool - if _pool is None: - _pool = multiprocessing.Pool(1, maxtasksperchild=1) modName = inspect.getmodule(self).__name__ clsName = self.__class__.__name__ funcName = inspect.currentframe().f_back.f_code.co_name - _pool.apply( + workerPool().apply( wrap_static_test_method, (modName, clsName, '_'+funcName, args, kwargs)) @@ -60,7 +69,6 @@ class IntegrationTest(unittest.TestCase): def setUp(self): self.mnt = tempfile.mkdtemp() run_test_server.authorize_with('active') - self.api = arvados.safeapi.ThreadSafeApiCache(arvados.config.settings()) def tearDown(self): os.rmdir(self.mnt) @@ -72,16 +80,19 @@ class IntegrationTest(unittest.TestCase): def decorator(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): - with arvados_fuse.command.Mount( - arvados_fuse.command.ArgumentParser().parse_args( - argv + ['--foreground', - '--unmount-timeout=0.1', - self.mnt])) as m: - return func(self, *args, **kwargs) - if m.llfuse_thread.is_alive(): - self.logger.warning("IntegrationTest.mount:" - " llfuse thread still alive after umount" - " -- killing test suite to avoid deadlock") - os.kill(os.getpid(), signal.SIGKILL) + self.mount = None + try: + with arvados_fuse.command.Mount( + arvados_fuse.command.ArgumentParser().parse_args( + argv + ['--foreground', + '--unmount-timeout=2', + self.mnt])) as self.mount: + return func(self, *args, **kwargs) + finally: + if self.mount and self.mount.llfuse_thread.is_alive(): + logging.warning("IntegrationTest.mount:" + " llfuse thread still alive after umount" + " -- killing test suite to avoid deadlock") + os.kill(os.getpid(), signal.SIGKILL) return wrapper return decorator