Exemplo n.º 1
0
    def test_writer_lock_initially_blocked_by_readers(self):
        """
        When a reader lock is already held, another thread/process should not be able
        to acquire the lock for writing until the reader releases its lock
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a reader lock is already acquired
        assert lock.acquire_read_lock() is True

        child_proc_function = dummy_fn_requiring_writer_lock
        timeout = 1
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same lock for writing, failing after 4 seconds
            res = pool.starmap_async(child_writer_dispatch, [(child_proc_function, lock_path, timeout, attempts)])

            # When: we verify that the writer lock is not immediately acquired
            with pytest.raises(TimeoutError):
                res.get(timeout=1)

            # When: the reader releases its lock
            lock.release_read_lock()

            # Expect: the child process to acquire the writer lock
            result = res.get(timeout=10)  # 10 second timeout to prevent a bad test from spoiling the fun
            assert result[0] == "A winner is you!"
Exemplo n.º 2
0
def read_cache_data(cachename):
    """Reads data from a cache file.

    :param cachename:

    """

    lock = fasteners.InterProcessReaderWriterLock(cachename + ".lock")
    with lock.read_lock():
        LOG.debug("Reading cache file: %s", cachename)
        try:
            with open(cachename, 'rb') as cache_fd:
                try:
                    data = pickle.load(cache_fd)
                except pickle.PickleError as exc:
                    raise MicroprobeCacheError(exc)
                except EOFError as exc:
                    raise MicroprobeCacheError(exc)
                except AttributeError as exc:
                    raise MicroprobeCacheError(exc)
                except TypeError as exc:
                    raise MicroprobeCacheError(exc)
                except ValueError as exc:
                    raise MicroprobeCacheError(exc)
                except ModuleNotFoundError as exc:
                    raise MicroprobeCacheError(exc)
        except FileNotFoundError as exc:
            raise MicroprobeCacheError(exc)
        except IOError as exc:
            raise MicroprobeCacheError(exc)

    return data
Exemplo n.º 3
0
    def test_writer_lock_timeout(self):
        """
        If a writer lock is already held, another process should not be able to acquire
        the same lock, failing after n attempts
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_fn = dummy_fn_requiring_writer_lock
        timeout = 0.25
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            res = pool.starmap_async(child_writer_dispatch, [(child_proc_fn, lock_path, timeout, attempts)])

            # Expect: the child to fail acquiring the writer lock (raises as FileKeyringLockTimeout)
            with pytest.raises(FileKeyringLockTimeout):
                # 10 second timeout to prevent a bad test from spoiling the fun (raises as TimeoutException)
                res.get(timeout=10)

        lock.release_write_lock()
Exemplo n.º 4
0
    def test_writer_lock_released_on_abort(self):
        """
        When a child process is holding the lock and aborts/crashes, we should be
        able to acquire the lock
        """
        # Avoid running on macOS: calling abort() triggers the CrashReporter prompt, interfering with automated testing
        if platform == "darwin":
            return

        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_function = dummy_abort_fn
        timeout = 0.25
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            res = pool.starmap_async(child_writer_dispatch, [(child_proc_function, lock_path, timeout, attempts)])

            # When: the writer lock is released
            lock.release_write_lock()

            # When: timing out waiting for the child process (because it aborted)
            with pytest.raises(TimeoutError):
                res.get(timeout=1)

            # Expect: Reacquiring the lock should succeed after the child exits, automatically releasing the lock
            assert lock.acquire_write_lock(timeout=(1)) is True
Exemplo n.º 5
0
    def test_writer_lock_reacquisition_failure(self):
        """
        After the child process acquires the writer lock (and sleeps), the previous
        holder should not be able to quickly reacquire the lock
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_function = dummy_sleep_fn  # Sleeps for DUMMY_SLEEP_VALUE seconds
        timeout = 0.25
        attempts = 8

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            pool.starmap_async(child_writer_dispatch, [(child_proc_function, lock_path, timeout, attempts)])

            # When: the writer lock is released
            lock.release_write_lock()

            # Brief delay to allow the child to acquire the lock
            sleep(1)

            # Expect: Reacquiring the lock should fail due to the child holding the lock and sleeping
            assert lock.acquire_write_lock(timeout=0.25) is False
Exemplo n.º 6
0
    def test_writer_lock_succeeds(self):
        """
        If a write lock is already held, another process will be able to acquire the
        same lock once the lock is released by the current holder
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_fn = dummy_fn_requiring_writer_lock
        timeout = 0.25
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            res = pool.starmap_async(child_writer_dispatch, [(child_proc_fn, lock_path, timeout, attempts)])

            # Brief delay to allow the child to timeout once
            sleep(0.25)

            # When: the writer lock is released
            lock.release_write_lock()

            # Expect: the child to acquire the writer lock
            result = res.get(timeout=10)  # 10 second timeout to prevent a bad test from spoiling the fun
            assert result[0] == "A winner is you!"
Exemplo n.º 7
0
    def test_writer_lock_initially_blocked_by_readers(self, ready_dir: Path,
                                                      finished_dir: Path):
        """
        When a reader lock is already held, another thread/process should not be able
        to acquire the lock for writing until the reader releases its lock
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(
            KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a reader lock is already acquired
        assert lock.acquire_read_lock() is True

        child_proc_function = dummy_fn_requiring_writer_lock
        timeout = 1
        attempts = 10
        num_workers = 1

        with Pool(processes=num_workers) as pool:
            # When: a child process attempts to acquire the same lock for writing, failing after 4 seconds
            res = pool.starmap_async(
                child_writer_dispatch_with_readiness_check,
                [(child_proc_function, lock_path, timeout, attempts, ready_dir,
                  finished_dir)],
            )

            # Wait up to 30 seconds for all processes to indicate readiness
            assert poll_directory(ready_dir, num_workers, 30) is True

            log.warning(f"Test setup complete: {num_workers} workers ready")

            # Signal that testing should begin
            start_file_path: Path = ready_dir / "start"
            with open(start_file_path, "w") as f:
                f.write(f"{os.getpid()}\n")

            # When: we verify that the writer lock is not immediately acquired
            with pytest.raises(TimeoutError):
                res.get(timeout=5)

            # When: the reader releases its lock
            lock.release_read_lock()

            # Wait up to 30 seconds for all processes to indicate completion
            assert poll_directory(finished_dir, num_workers, 30) is True

            log.warning(f"Finished: {num_workers} workers finished")

            # Expect: the child process to acquire the writer lock
            result = res.get(
                timeout=10
            )  # 10 second timeout to prevent a bad test from spoiling the fun
            assert result[0] == "A winner is you!"
Exemplo n.º 8
0
    def test_writer_lock_succeeds(self, ready_dir: Path, finished_dir: Path):
        """
        If a write lock is already held, another process will be able to acquire the
        same lock once the lock is released by the current holder
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(
            KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_fn = dummy_fn_requiring_writer_lock
        timeout = 0.25
        attempts = 8
        num_workers = 1

        with Pool(processes=num_workers) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            res = pool.starmap_async(
                child_writer_dispatch_with_readiness_check,
                [(child_proc_fn, lock_path, timeout, attempts, ready_dir,
                  finished_dir)],
            )

            # Wait up to 30 seconds for all processes to indicate readiness
            assert poll_directory(ready_dir, num_workers, 30) is True

            log.warning(f"Test setup complete: {num_workers} workers ready")

            # Signal that testing should begin
            start_file_path: Path = ready_dir / "start"
            with open(start_file_path, "w") as f:
                f.write(f"{os.getpid()}\n")

            # Brief delay to allow the child to timeout once
            sleep(0.50)

            # When: the writer lock is released
            lock.release_write_lock()

            # Expect: the child to acquire the writer lock
            result = res.get(
                timeout=10
            )  # 10 second timeout to prevent a bad test from spoiling the fun
            assert result[0] == "A winner is you!"

            # Wait up to 30 seconds for all processes to indicate completion
            assert poll_directory(finished_dir, num_workers, 30) is True

            log.warning(f"Finished: {num_workers} workers finished")
Exemplo n.º 9
0
    def test_writer_lock_reacquisition_failure(self, ready_dir: Path,
                                               finished_dir: Path):
        """
        After the child process acquires the writer lock (and sleeps), the previous
        holder should not be able to quickly reacquire the lock
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(
            KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_function = dummy_sleep_fn  # Sleeps for DUMMY_SLEEP_VALUE seconds
        timeout = 0.25
        attempts = 8
        num_workers = 1

        with Pool(processes=num_workers) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            pool.starmap_async(
                child_writer_dispatch_with_readiness_check,
                [(child_proc_function, lock_path, timeout, attempts, ready_dir,
                  finished_dir)],
            )

            # Wait up to 30 seconds for all processes to indicate readiness
            assert poll_directory(ready_dir, num_workers, 30) is True

            log.warning(f"Test setup complete: {num_workers} workers ready")

            # Signal that testing should begin
            start_file_path: Path = ready_dir / "start"
            with open(start_file_path, "w") as f:
                f.write(f"{os.getpid()}\n")

            # When: the writer lock is released
            lock.release_write_lock()

            # Brief delay to allow the child to acquire the lock
            sleep(1)

            # Expect: Reacquiring the lock should fail due to the child holding the lock and sleeping
            assert lock.acquire_write_lock(timeout=0.25) is False

            # Wait up to 30 seconds for all processes to indicate completion
            assert poll_directory(finished_dir, num_workers, 30) is True

            log.warning(f"Finished: {num_workers} workers finished")
Exemplo n.º 10
0
    def test_writer_lock_blocked_by_readers(self, ready_dir: Path,
                                            finished_dir: Path):
        """
        When a reader lock is already held, another thread/process should not be able
        to acquire the lock for writing
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(
            KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a reader lock is already held
        lock.acquire_read_lock()

        child_proc_function = dummy_fn_requiring_writer_lock
        timeout = 0.25
        attempts = 4
        num_workers = 1

        with Pool(processes=num_workers) as pool:
            # When: a child process attempts to acquire the same lock for writing, failing after 1 second
            res = pool.starmap_async(
                child_writer_dispatch_with_readiness_check,
                [(child_proc_function, lock_path, timeout, attempts, ready_dir,
                  finished_dir)],
            )

            # Wait up to 30 seconds for all processes to indicate readiness
            assert poll_directory(ready_dir, num_workers, 30) is True

            log.warning(f"Test setup complete: {num_workers} workers ready")

            # Signal that testing should begin
            start_file_path: Path = ready_dir / "start"
            with open(start_file_path, "w") as f:
                f.write(f"{os.getpid()}\n")

            # Wait up to 30 seconds for all processes to indicate completion
            assert poll_directory(finished_dir, num_workers, 30) is True

            log.warning(f"Finished: {num_workers} workers finished")

            # Expect: lock acquisition times out (raises as FileKeyringLockTimeout)
            with pytest.raises(FileKeyringLockTimeout):
                res.get(timeout=30)

        lock.release_read_lock()
Exemplo n.º 11
0
def acquire_reader_lock(lock_path: Path, timeout=5, max_iters=6):
    lock = fasteners.InterProcessReaderWriterLock(str(lock_path))
    result = None
    for i in range(0, max_iters):
        if lock.acquire_read_lock(timeout=timeout):
            yield  # <----
            lock.release_read_lock()
            break
        else:
            print(
                f"Failed to acquire keyring reader lock after {timeout} seconds.",
                end="")
            if i < max_iters - 1:
                print(f" Remaining attempts: {max_iters - 1 - i}")
            else:
                print("")
                raise FileKeyringLockTimeout(
                    "Exhausted all attempts to acquire the writer lock")
    return result
Exemplo n.º 12
0
def write_cache_data(filename, data, data_reload=False):
    """Writes data to a cache file.

    :param filename:
    :param data:

    """
    LOG.debug("Writing cache file: %s", filename)

    if data_reload:
        try:
            base_data = read_cache_data(filename)
        except MicroprobeCacheError as exc:
            base_data = None

        if base_data is not None:
            if type(base_data) != type(data):
                pass
            if isinstance(base_data, dict):
                # TODO: Control cache size of dictionary caches
                data.update(base_data)
            elif isinstance(base_data, cachetools.LRUCache):
                pass
            else:
                raise NotImplementedError

    lock = fasteners.InterProcessReaderWriterLock(filename + ".lock")

    if lock.acquire_write_lock(timeout=10):
        try:
            with open(filename, 'wb') as cache_fd:
                pickle.dump(data, cache_fd, protocol=pickle.HIGHEST_PROTOCOL)
        except IOError:
            # Unable to create cache files, disabling cache
            MICROPROBE_RC['no_cache'] = True
        except pickle.PickleError as exc:
            raise MicroprobeCacheError(exc)
        except EOFError as exc:
            raise MicroprobeCacheError(exc)
Exemplo n.º 13
0
    def test_writer_lock_blocked_by_readers(self):
        """
        When a reader lock is already held, another thread/process should not be able
        to acquire the lock for writing
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a reader lock is already held
        lock.acquire_read_lock()

        child_proc_function = dummy_fn_requiring_writer_lock
        timeout = 0.25
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same lock for writing, failing after 1 second
            res = pool.starmap_async(child_writer_dispatch, [(child_proc_function, lock_path, timeout, attempts)])

            # Expect: lock acquisition times out (raises as FileKeyringLockTimeout)
            with pytest.raises(FileKeyringLockTimeout):
                res.get(timeout=2)
Exemplo n.º 14
0
    def test_writer_lock_reacquisition_success(self):
        """
        After the child process releases the writer lock, we should be able to
        acquire the lock
        """
        lock_path = FileKeyring.lockfile_path_for_file_path(KeyringWrapper.get_shared_instance().keyring.keyring_path)
        lock = fasteners.InterProcessReaderWriterLock(str(lock_path))

        # When: a writer lock is already acquired
        lock.acquire_write_lock()

        child_proc_function = dummy_sleep_fn  # Sleeps for DUMMY_SLEEP_VALUE seconds
        timeout = 0.25
        attempts = 4

        with Pool(processes=1) as pool:
            # When: a child process attempts to acquire the same writer lock, failing after 1 second
            pool.starmap_async(child_writer_dispatch, [(child_proc_function, lock_path, timeout, attempts)])

            # When: the writer lock is released
            lock.release_write_lock()

            # Expect: Reacquiring the lock should succeed after the child finishes and releases the lock
            assert lock.acquire_write_lock(timeout=(DUMMY_SLEEP_VALUE + 0.25)) is True
Exemplo n.º 15
0
}
BUILD_SHARED_LIBS = {'static': 'off', 'shared': 'on'}
LLVM_PROJECT_LABELS = [
    'llvm_project_sha1', 'llvm_project_sha1_date',
    'llvm_project_dockerfile_sha1'
]

GITHUB_REPO_NAME = github_repo_name.upper()
GITHUB_REPO_NAME2 = github_repo_name2.upper()

DOCKER_DIST_MANIFESTS = {
    'v1': 'application/vnd.docker.distribution.manifest.v1+json',
    'v2': 'application/vnd.docker.distribution.manifest.v2+json'
}

docker_rwlock = fasteners.InterProcessReaderWriterLock(docker_pushpull_rwlock)
docker_api = docker.APIClient(base_url=docker_daemon_socket)


# Validate whether the commit sha1 date is a valid UTC ISO 8601 date
def valid_sha1_date(sha1_date):
    try:
        datetime.datetime.strptime(sha1_date, '%Y-%m-%dT%H:%M:%SZ')
        return True
    except:
        return False


# Extract a regex pattern from a file. Used to get llvm-project sha1
# from utils/clone-mlir.sh.
def extract_pattern_from_file(file_name, regex_pattern):
Exemplo n.º 16
0
 def __init__(self, path: PathLikeFrom) -> None:
     """Creates a lockfile at path."""
     super().__init__()
     self.path = pathlike_from(path)
     self._rw_lock = fasteners.InterProcessReaderWriterLock(
         cast(Path, self.path))