diff --git a/src/agh/agh_data.py b/src/agh/agh_data.py index 419c526..b156b1a 100644 --- a/src/agh/agh_data.py +++ b/src/agh/agh_data.py @@ -1013,8 +1013,9 @@ def __init__(self, **kwargs): self.__post_init__() - def save(self): + def save(self) -> Self: super().save(self.evaluation_directory / self.SUBMISSION_FILE_NAME) + return self @classmethod def get_anon_name(cls, assignment: Assignment, submission_file: pathlib.Path): @@ -1242,13 +1243,13 @@ def addError(self, key: str, txt_or_markdown: str) -> "Submission": """ # DON'T USE the property above. It adds transient errors. Just get the metadata and add to it. - return self._setErrWarnItem("errors", key, txt_or_markdown) + return self._setErrWarnItem("errors", key, txt_or_markdown).save() # errors: list[str] = self.getMetadata(META_AGH_INTERNAL_KEY, META_INTERNAL_SUB_KEY, "errors", default=[]) # errors.append(txt_or_markdown) # return self.setMetadata(META_AGH_INTERNAL_KEY, META_INTERNAL_SUB_KEY, "errors", value=errors) def delError(self, key: str) -> "Submission": - return self._delErrWarnItem("errors", key) + return self._delErrWarnItem("errors", key).save() @property def warnings(self) -> None | list[str]: @@ -1261,7 +1262,7 @@ def addWarning(self, key: str, txt_or_markdown: str) -> "Submission": """Add a warning to the submission. These are NOT testing warnings, but anything possibly preventing the submission from being tested. """ - return self._setErrWarnItem("warnings", key, txt_or_markdown) + return self._setErrWarnItem("warnings", key, txt_or_markdown).save() def delWarning(self, key: str) -> "Submission": - return self._delErrWarnItem("warnings", key) + return self._delErrWarnItem("warnings", key).save() diff --git a/src/agh/pytest_plugin.py b/src/agh/pytest_plugin.py index 30f8f44..15c3182 100644 --- a/src/agh/pytest_plugin.py +++ b/src/agh/pytest_plugin.py @@ -198,6 +198,10 @@ def run_executable( if handle_core_dump: shell_cmd_line = "ulimit -c unlimited && " + shell_cmd_line + # Clear any old core files. + for core_file in agh_submission.evaluation_directory.glob(f"{CORE_DUMP_FILE_NAME}.*"): + core_file.unlink() + result = shell.run(shell_cmd_line, shell=True, cwd=agh_submission.evaluation_directory, **kwargs) if parent_section is None: @@ -230,21 +234,34 @@ def run_executable( ) std_err_file.write_text(result.stderr, encoding="ascii", errors="backslashreplace") - # Handle core dumps. - core_dump_file = agh_submission.evaluation_directory / CORE_DUMP_FILE_NAME - if core_dump_file.exists(): + # Handle core dumps. We now in ubuntu need to search for CORE_DUMP_FILE_NAME.pid. + # core_dump_file = agh_submission.evaluation_directory / CORE_DUMP_FILE_NAME + agh_submission.delWarning("crash_detected") + agh_submission.delError("crash_detection_issue") + + core_dump_files = [*agh_submission.evaluation_directory.glob(f"{CORE_DUMP_FILE_NAME}.*")] + core_dump_file = core_dump_files[0] if len(core_dump_files) > 0 else None + if core_dump_file and core_dump_file.exists(): + agh_submission.addWarning( + "crash_detected", 'The submission crashed. Check the "Backtrace from Debug" section for more details.' + ) # Run gdb on the core dump + + debug_output_file = resultsDir / (test_key + ".backtrace") result_debug = shell.run( - f'gdb. / {test_exe_file} {core_dump_file.name} --eval-command "thread apply all bt full" --batch', + f'gdb -q {test_exe_file} {core_dump_file.name} --ex "thread apply all bt full" --batch > {debug_output_file} 2>&1', shell=True, cwd=agh_submission.evaluation_directory, ) core_dump_file.unlink() - if len(result_debug.stdout) > 0: + if result_debug.returncode != 0: + agh_submission.addError("crash_detection_issue", "**ERROR:** gdb failed to run on the core dump!") + + if debug_output_file.exists() and debug_output_file.stat().st_size > 0: # There is data add to the eval section. - debug_output_file = resultsDir / (test_key + ".backtrace") - debug_output_file.write_text(result_debug.stdout) + # debug_output_file.write_text(result_debug.stdout) + # debug_output_file.write_text(result_debug.stderr, encoding="ascii", errors="backslashreplace") current_out_section.included_files.append( SubmissionFileData( path=debug_output_file.relative_to(agh_submission.evaluation_directory), @@ -255,7 +272,9 @@ def run_executable( ) else: # todo: Handle this better. - current_out_section.text += "\n\n**Warning:** no backtrace data available from core file!" + agh_submission.addError( + "crash_detection_issue", "**Warning:** no backtrace data available from core file!\n" + str(result_debug.cmdline) + ) err_code = result.returncode if err_code: