From af82c14d17fdb1f141687c415e5c306666c48c35 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Thu, 31 Oct 2024 10:44:20 -0400 Subject: [PATCH] Fix for proto files not being viewable in Perfetto UI Ported from https://github.com/ROCm/omnitrace/pull/411 Signed-off-by: David Galiffi --- source/lib/core/config.cpp | 72 +++++++++++++++++++++++++++++------- source/lib/core/config.hpp | 7 ++++ source/lib/core/perfetto.cpp | 38 +++++++++++-------- 3 files changed, 87 insertions(+), 30 deletions(-) diff --git a/source/lib/core/config.cpp b/source/lib/core/config.cpp index c519dfd7..9ed5f840 100644 --- a/source/lib/core/config.cpp +++ b/source/lib/core/config.cpp @@ -2454,18 +2454,37 @@ tmp_file::~tmp_file() remove(); } -bool -tmp_file::open(std::ios::openmode _mode) -{ - ROCPROFSYS_BASIC_VERBOSE(2, "Opening temporary file '%s'...\n", filename.c_str()); - +void +tmp_file::touch() const + { if(!filepath::exists(filename)) { // if the filepath does not exist, open in out mode to create it - std::ofstream _ofs{}; + auto _ofs = std::ofstream{}; filepath::open(_ofs, filename); } +} + +bool +tmp_file::open(int _mode, int _perms) +{ + ROCPROFSYS_BASIC_VERBOSE(2, "Opening temporary file '%s'...\n", filename.c_str()); + touch(); + m_pid = getpid(); + fd = ::open(filename.c_str(), _mode, _perms); + + return (fd > 0); +} + +bool +tmp_file::open(std::ios::openmode _mode) +{ + ROCPROFSYS_BASIC_VERBOSE(2, "Opening temporary file '%s'...\n", filename.c_str()); + + touch(); + + m_pid = getpid(); stream.open(filename, _mode); return (stream.is_open() && stream.good()); @@ -2476,14 +2495,10 @@ tmp_file::fopen(const char* _mode) { ROCPROFSYS_BASIC_VERBOSE(2, "Opening temporary file '%s'...\n", filename.c_str()); - if(!filepath::exists(filename)) - { - // if the filepath does not exist, open in out mode to create it - std::ofstream _ofs{}; - filepath::open(_ofs, filename); - } + touch(); - file = filepath::fopen(filename, _mode); + m_pid = getpid(); + file = filepath::fopen(filename, _mode); if(file) fd = ::fileno(file); return (file != nullptr && fd > 0); @@ -2492,6 +2507,8 @@ tmp_file::fopen(const char* _mode) bool tmp_file::flush() { + if(m_pid != getpid()) return false; + if(stream.is_open()) { stream.flush(); @@ -2508,6 +2525,18 @@ tmp_file::flush() } return (_ret == 0); } + else if(fd > 0) + { + int _ret = ::fsync(fd); + int _cnt = 0; + while(_ret == EAGAIN || _ret == EINTR) + { + std::this_thread::sleep_for(std::chrono::milliseconds{ 100 }); + _ret = ::fsync(fd); + if(++_cnt > 10) break; + } + return (_ret == 0); + } return true; } @@ -2517,6 +2546,8 @@ tmp_file::close() { flush(); + if(m_pid != getpid()) return false; + if(stream.is_open()) { stream.close(); @@ -2532,6 +2563,15 @@ tmp_file::close() } return (_ret == 0); } + else if(fd > 0) + { + auto _ret = ::close(fd); + if(_ret == 0) + { + fd = -1; + } + return (_ret == 0); + } return true; } @@ -2539,6 +2579,8 @@ tmp_file::close() bool tmp_file::remove() { + if(m_pid != getpid()) return false; + close(); if(filepath::exists(filename)) { @@ -2553,7 +2595,9 @@ tmp_file::remove() tmp_file::operator bool() const { - return (stream.is_open() && stream.good()) || (file != nullptr && fd > 0); + return (m_pid == getpid()) && + ((stream.is_open() && stream.good()) || (file != nullptr && fd > 0) || + (file == nullptr && fd > 0)); } std::shared_ptr diff --git a/source/lib/core/config.hpp b/source/lib/core/config.hpp index 2b9847bc..2ccbce23 100644 --- a/source/lib/core/config.hpp +++ b/source/lib/core/config.hpp @@ -374,6 +374,7 @@ struct tmp_file tmp_file(std::string); ~tmp_file(); + bool open(int, int); bool open(std::ios::openmode = std::ios::binary | std::ios::in | std::ios::out); bool fopen(const char* = "r+"); bool flush(); @@ -386,6 +387,12 @@ struct tmp_file std::fstream stream = {}; FILE* file = nullptr; int fd = -1; + +private: + void touch() const; + +private: + pid_t m_pid = getpid(); }; std::shared_ptr diff --git a/source/lib/core/perfetto.cpp b/source/lib/core/perfetto.cpp index ac2c2e50..c3b84d90 100644 --- a/source/lib/core/perfetto.cpp +++ b/source/lib/core/perfetto.cpp @@ -22,10 +22,13 @@ #include "perfetto.hpp" #include "config.hpp" +#include "debug.hpp" #include "library/runtime.hpp" #include "perfetto_fwd.hpp" #include "utility.hpp" +#include + namespace rocprofsys { namespace perfetto @@ -120,18 +123,18 @@ start() if(!_tmp_file) { _tmp_file = config::get_tmp_file("perfetto-trace", "proto"); - _tmp_file->fopen("w+"); - } - else - { - ROCPROFSYS_VERBOSE(2, "Resuming perfetto...\n"); - _tmp_file->fopen("a+"); + _tmp_file->open(O_RDWR | O_CREAT | O_TRUNC, 0600); } } ROCPROFSYS_VERBOSE(2, "Setup perfetto...\n"); int _fd = (_tmp_file) ? _tmp_file->fd : -1; auto& cfg = get_config(); + tracing_session->SetOnErrorCallback([](::perfetto::TracingError _err) { + if(_err.code == ::perfetto::TracingError::kTracingFailed) + ROCPROFSYS_WARNING(0, "perfetto encountered a tracing error: %s\n", + _err.message.c_str()); + }); tracing_session->Setup(cfg, _fd); tracing_session->StartBlocking(); } @@ -174,7 +177,7 @@ post_process(tim::manager* _timemory_manager, bool& _perfetto_output_error) if(_tmp_file && *_tmp_file) { _tmp_file->close(); - FILE* _fdata = fopen(_tmp_file->filename.c_str(), "rb"); + FILE* _fdata = ::fopen(_tmp_file->filename.c_str(), "rb"); if(!_fdata) { @@ -184,22 +187,25 @@ post_process(tim::manager* _timemory_manager, bool& _perfetto_output_error) return char_vec_t{ tracing_session->ReadTraceBlocking() }; } - fseek(_fdata, 0, SEEK_END); - size_t _fnum_elem = ftell(_fdata); - fseek(_fdata, 0, SEEK_SET); // same as rewind(f); + ::fseek(_fdata, 0, SEEK_END); + size_t _fnum_elem = ::ftell(_fdata); + ::fseek(_fdata, 0, SEEK_SET); // same as rewind(f); - _data.resize(_fnum_elem + 1); - auto _fnum_read = fread(_data.data(), sizeof(char), _fnum_elem, _fdata); - fclose(_fdata); + _data.resize(_fnum_elem, '\0'); + auto _fnum_read = ::fread(_data.data(), sizeof(char), _fnum_elem, _fdata); + ::fclose(_fdata); ROCPROFSYS_CI_THROW( _fnum_read != _fnum_elem, "Error! read %zu elements from perfetto trace file '%s'. Expected %zu\n", _fnum_read, _tmp_file->filename.c_str(), _fnum_elem); } + else + { + _data = char_vec_t{ tracing_session->ReadTraceBlocking() }; + } - return utility::combine(_data, - char_vec_t{ tracing_session->ReadTraceBlocking() }); + return _data; }; auto trace_data = char_vec_t{}; @@ -251,7 +257,7 @@ post_process(tim::manager* _timemory_manager, bool& _perfetto_output_error) else { // Write the trace into a file. - ofs.write(&trace_data[0], trace_data.size()); + ofs.write(trace_data.data(), trace_data.size()); if(config::get_verbose() >= 0) _fom.append("%s", "Done"); // NOLINT if(_timemory_manager) _timemory_manager->add_file_output("protobuf", "perfetto", _filename);