Ejemplo n.º 1
0
    def _recover_core(self):
        core_path = cores.recover_core_dump_file(self.command[0], self._cwd, self.process.pid)
        if core_path:
            # Core dump file recovering may be disabled (for distbuild for example) - produce only bt
            store_cores = runtime._get_ya_config().collect_cores
            if store_cores:
                new_core_path = path.get_unique_file_path(runtime.output_path(), "{}.{}.core".format(os.path.basename(self.command[0]), self._process.pid))
                # Copy core dump file, because it may be overwritten
                yatest_logger.debug("Coping core dump file from '%s' to the '%s'", core_path, new_core_path)
                shutil.copyfile(core_path, new_core_path)
                core_path = new_core_path

            bt_filename = None
            pbt_filename = None

            if os.path.exists(runtime.gdb_path()):
                self._backtrace = cores.get_gdb_full_backtrace(self.command[0], core_path, runtime.gdb_path())
                bt_filename = path.get_unique_file_path(runtime.output_path(), "{}.{}.backtrace".format(os.path.basename(self.command[0]), self._process.pid))
                with open(bt_filename, "w") as afile:
                    afile.write(self._backtrace)
                # generate pretty html version of backtrace aka Tri Korochki
                pbt_filename = bt_filename + ".html"
                cores.backtrace_to_html(bt_filename, pbt_filename)

            if store_cores:
                runtime._register_core(os.path.basename(self.command[0]), self.command[0], core_path, bt_filename, pbt_filename)
            else:
                runtime._register_core(os.path.basename(self.command[0]), None, None, bt_filename, pbt_filename)
Ejemplo n.º 2
0
 def verify_sanitize_errors(self):
     """
     Verify there are no sanitizer (ASAN, MSAN, TSAN, etc) errors for this binary. If there are any report them.
     """
     if self._std_err and self._check_sanitizer and runtime._get_ya_config().sanitizer_extra_checks:
         build_path = runtime.build_path()
         if self.command[0].startswith(build_path):
             match = re.search(SANITIZER_ERROR_PATTERN, self._std_err)
             if match:
                 yatest_logger.error("%s sanitizer found errors:\n\tstd_err:%s\n", match.group(1), truncate(self.std_err, MAX_OUT_LEN))
                 raise ExecutionError(self)
             else:
                 yatest_logger.debug("No sanitizer errors found")
         else:
             yatest_logger.debug("'%s' doesn't belong to '%s' - no check for sanitize errors", self.command[0], build_path)
Ejemplo n.º 3
0
    def wait(self, check_exit_code=True, timeout=None, on_timeout=None):
        def _wait():
            finished = None
            try:
                if hasattr(os, "wait4"):
                    try:
                        pid, sts, rusage = subprocess._eintr_retry_call(
                            os.wait4, self._process.pid, 0)
                        finished = time.time()
                        self._process._handle_exitstatus(sts)
                        for field in [
                                "ru_idrss",
                                "ru_inblock",
                                "ru_isrss",
                                "ru_ixrss",
                                "ru_majflt",
                                "ru_maxrss",
                                "ru_minflt",
                                "ru_msgrcv",
                                "ru_msgsnd",
                                "ru_nivcsw",
                                "ru_nsignals",
                                "ru_nswap",
                                "ru_nvcsw",
                                "ru_oublock",
                                "ru_stime",
                                "ru_utime",
                        ]:
                            if hasattr(rusage, field):
                                self._metrics[field.replace("ru_",
                                                            "")] = getattr(
                                                                rusage, field)
                    except OSError as exc:

                        if exc.errno == errno.ECHILD:
                            yatest_logger.debug(
                                "Process resource usage is not available as process finished before wait4 was called"
                            )
                        else:
                            raise
            finally:
                self._process.wait(
                )  # this has to be here unconditionally, so that all process properties are set

            if not finished:
                finished = time.time()
            self._metrics["wtime"] = round(finished - self._started, 3)

        try:
            if timeout:
                process_is_finished = lambda: not self.running
                fail_message = "Command '%s' stopped by %d seconds timeout" % (
                    self._command, timeout)
                try:
                    wait_for(
                        process_is_finished,
                        timeout,
                        fail_message,
                        sleep_time=0.1,
                        on_check_condition=self._process_progress_listener)
                except TimeoutError as e:
                    if on_timeout:
                        yatest_logger.debug(
                            "Calling user specified on_timeout function")
                        try:
                            on_timeout(self, timeout)
                        except Exception:
                            yatest_logger.exception(
                                "Exception while calling on_timeout")
                    raise ExecutionTimeoutError(self, str(e))
            # Wait should be always called here, it finalizes internal states of its process and sets up return code
            _wait()
        except BaseException as e:
            _kill_process_tree(self._process.pid)
            _wait()
            yatest_logger.debug("Command exception: %s", e)
            raise
        finally:
            self._elapsed = time.time() - self._start
            self._save_outputs()

            if self.exit_code < 0 and self._collect_cores:
                try:
                    self._recover_core()
                except Exception:
                    yatest_logger.exception("Exception while recovering core")

        # Set the signal (negative number) which caused the process to exit
        if check_exit_code and self.exit_code != 0:
            yatest_logger.error(
                "Execution failed with exit code: %s\n\t,std_out:%s\n\tstd_err:%s\n",
                self.exit_code, truncate(self.std_out, MAX_OUT_LEN),
                truncate(self.std_err, MAX_OUT_LEN))
            raise ExecutionError(self)

        # Don't search for sanitize errors if stderr was redirected
        if self._std_err and self._check_sanitizer and runtime._get_ya_config(
        ).sanitizer_extra_checks:
            build_path = runtime.build_path()
            if self.command[0].startswith(build_path):
                match = re.search(SANITIZER_ERROR_PATTERN, self._std_err)
                if match:
                    yatest_logger.error(
                        "%s sanitizer found errors:\n\tstd_err:%s\n",
                        match.group(1), truncate(self.std_err, MAX_OUT_LEN))
                    raise ExecutionError(self)
                    yatest_logger.debug("No sanitizer errors found")
            else:
                yatest_logger.debug(
                    "'%s' doesn't belong to '%s' - no check for sanitize errors",
                    self.command[0], build_path)