Beispiel #1
0
    def _run_and_return_roots(self, session, execution_request):
        def python_signal() -> bool:
            """This function checks to see whether the main Python thread has responded to a signal.

            It is invoked by the Rust scheduler, and if it returns true, the scheduler will
            gracefully shut down.
            """
            return ExceptionSink.signal_sent() is not None

        try:
            raw_roots = self._native.lib.scheduler_execute(
                self._scheduler,
                session,
                execution_request,
                python_signal,
            )
        except self._native.lib.PollTimeout:
            raise ExecutionTimeoutError("Timed out")

        return [
            Throw(
                raw_root.result(),
                python_traceback=raw_root.python_traceback(),
                engine_traceback=raw_root.engine_traceback(),
            ) if raw_root.is_throw() else Return(raw_root.result())
            for raw_root in raw_roots
        ]
Beispiel #2
0
    def _run_and_return_roots(self, session, execution_request):
        raw_roots = self._native.lib.scheduler_execute(self._scheduler,
                                                       session,
                                                       execution_request)
        if raw_roots.err == self._native.lib.NoError:
            pass
        elif raw_roots.err == self._native.lib.KeyboardInterrupt:
            raise KeyboardInterrupt
        elif raw_roots.err == self._native.lib.Timeout:
            raise ExecutionTimeoutError("Timed out")
        else:
            raise Exception(
                f"Unrecognized error type from native execution: {raw_roots.err}"
            )

        remaining_runtime_exceptions_to_capture = list(
            self._native.consume_cffi_extern_method_runtime_exceptions())
        try:
            roots = []
            for raw_root in self._native.unpack(raw_roots.nodes_ptr,
                                                raw_roots.nodes_len):
                # Check if there were any uncaught exceptions within rules that were executed.
                remaining_runtime_exceptions_to_capture.extend(
                    self._native.consume_cffi_extern_method_runtime_exceptions(
                    ))

                if raw_root.is_throw:
                    state = Throw(self._from_value(raw_root.handle))
                elif raw_root.handle == self._native.ffi.NULL:
                    # NB: We expect all NULL handles to correspond to uncaught exceptions which are collected
                    # in `self._native._peek_cffi_extern_method_runtime_exceptions()`!
                    if not remaining_runtime_exceptions_to_capture:
                        raise ExecutionError(
                            "Internal logic error in scheduler: expected more elements in "
                            "`self._native._peek_cffi_extern_method_runtime_exceptions()`."
                        )
                    matching_runtime_exception = remaining_runtime_exceptions_to_capture.pop(
                        0)
                    state = Throw(matching_runtime_exception)
                else:
                    state = Return(self._from_value(raw_root.handle))
                roots.append(state)
        finally:
            self._native.lib.nodes_destroy(raw_roots)

        if remaining_runtime_exceptions_to_capture:
            raise ExecutionError(
                "Internal logic error in scheduler: expected elements in "
                "`self._native._peek_cffi_extern_method_runtime_exceptions()`."
            )
        return roots
Beispiel #3
0
    def _run_and_return_roots(self, session, execution_request):
        try:
            raw_roots = self._native.lib.scheduler_execute(
                self._scheduler, session, execution_request)
        except self._native.lib.PollTimeout:
            raise ExecutionTimeoutError("Timed out")

        return [
            Throw(
                raw_root.result(),
                python_traceback=raw_root.python_traceback(),
                engine_traceback=raw_root.engine_traceback(),
            ) if raw_root.is_throw() else Return(raw_root.result())
            for raw_root in raw_roots
        ]
Beispiel #4
0
    def execute(
        self, execution_request: ExecutionRequest
    ) -> tuple[tuple[tuple[Any, Return], ...], tuple[tuple[Any, Throw], ...]]:
        """Invoke the engine for the given ExecutionRequest, returning Return and Throw states.

        :return: A tuple of (root, Return) tuples and (root, Throw) tuples.
        """
        start_time = time.time()
        try:
            raw_roots = native_engine.scheduler_execute(
                self.py_scheduler,
                self.py_session,
                execution_request.native,
            )
        except native_engine.PollTimeout:
            raise ExecutionTimeoutError("Timed out")

        states = [
            Throw(
                raw_root.result(),
                python_traceback=raw_root.python_traceback(),
                engine_traceback=raw_root.engine_traceback(),
            ) if raw_root.is_throw() else Return(raw_root.result())
            for raw_root in raw_roots
        ]

        roots = list(zip(execution_request.roots, states))

        self._maybe_visualize()
        logger.debug(
            "computed %s nodes in %f seconds. there are %s total nodes.",
            len(roots),
            time.time() - start_time,
            self._scheduler.graph_len(),
        )

        returns = tuple((root, state) for root, state in roots
                        if isinstance(state, Return))
        throws = tuple(
            (root, state) for root, state in roots if isinstance(state, Throw))
        return returns, throws