diff --git a/src/emu/ovni/setup.c b/src/emu/ovni/setup.c index fe6622a..a6e8795 100644 --- a/src/emu/ovni/setup.c +++ b/src/emu/ovni/setup.c @@ -118,7 +118,27 @@ static const struct model_thread_spec th_spec = { int model_ovni_probe(struct emu *emu) { - return model_version_probe(&model_ovni, emu); + int ret = model_version_probe(&model_ovni, emu); + + if (ret < 0) { + err("model_version_probe failed for ovni model"); + return -1; + } + + /* Ensure all threads finished by setting the 'ovni.finished' flag, + * otherwise the trace can be inconsistent */ + struct system *sys = &emu->system; + for (struct thread *t = sys->threads; t; t = t->gnext) { + if (t->meta == NULL) + continue; + + if (json_object_dotget_number(t->meta, "ovni.finished") == 0) + warn("incomplete stream: %s", t->id); + } + + + /* The ovni model is always enabled */ + return 1; } int diff --git a/src/emu/thread.c b/src/emu/thread.c index fcedbe4..eda4d23 100644 --- a/src/emu/thread.c +++ b/src/emu/thread.c @@ -458,6 +458,9 @@ thread_load_metadata(struct thread *thread, JSON_Object *meta) return -1; } + if (json_object_dotget_number(meta, "ovni.finished") != 1) + warn("thread didn't finish properly: %s", thread->id); + thread->meta = meta; return 0; diff --git a/src/rt/ovni.c b/src/rt/ovni.c index 65b06e7..3978daa 100644 --- a/src/rt/ovni.c +++ b/src/rt/ovni.c @@ -571,6 +571,17 @@ ovni_thread_free(void) if (!rthread.ready) die("thread not initialized"); + JSON_Object *meta = json_value_get_object(rthread.meta); + + if (meta == NULL) + die("json_value_get_object failed"); + + /* Mark it finished so we can detect partial streams */ + if (json_object_dotset_number(meta, "ovni.finished", 1) != 0) + die("json_object_dotset_string failed"); + + thread_metadata_store(); + free(rthread.evbuf); } diff --git a/test/emu/ovni/CMakeLists.txt b/test/emu/ovni/CMakeLists.txt index cae7548..a3a1cb5 100644 --- a/test/emu/ovni/CMakeLists.txt +++ b/test/emu/ovni/CMakeLists.txt @@ -20,3 +20,4 @@ test_emu(tracedir-subdir.c MP DRIVER "tracedir-subdir.driver.sh") test_emu(empty-stream.c SHOULD_FAIL REGEX "model_ovni_finish: thread .* is not dead") test_emu(require.c SHOULD_FAIL REGEX "unsupported ovni model version (want 666.66.6, have .*)") test_emu(no-require.c REGEX "loading trace in compatibility mode") +test_emu(thread-crash.c SHOULD_FAIL REGEX "incomplete stream") diff --git a/test/emu/ovni/thread-crash.c b/test/emu/ovni/thread-crash.c new file mode 100644 index 0000000..08769c5 --- /dev/null +++ b/test/emu/ovni/thread-crash.c @@ -0,0 +1,19 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "instr.h" + +/* Emulate a crash in one thread by not calling ovni_thread_free(). We need to + * call ovni_proc_fini() otherwise the metadata won't appear */ + +int +main(void) +{ + instr_start(0, 1); + + ovni_flush(); + ovni_proc_fini(); + + return 0; +}