Skip to content

Commit

Permalink
DPL GUI: add GUI to list devices preventing quitting
Browse files Browse the repository at this point in the history
  • Loading branch information
ktf committed Nov 16, 2023
1 parent 73eddeb commit 7f758d4
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 42 deletions.
4 changes: 3 additions & 1 deletion Framework/Core/include/Framework/DebugGUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
namespace o2::framework
{
struct ServiceRegistry;
struct GuiCallbackContext;
/// Plugin interface for DPL GUIs.
struct DebugGUI {
virtual std::function<void(void)> getGUIDebugger(std::vector<o2::framework::DeviceInfo> const& infos,
Expand All @@ -35,7 +36,8 @@ struct DebugGUI {
std::vector<o2::framework::DeviceMetricsInfo> const& metricsInfos,
o2::framework::DriverInfo const& driverInfo,
std::vector<o2::framework::DeviceControl>& controls,
o2::framework::DriverControl& driverControl) = 0;
o2::framework::DriverControl& driverControl,
GuiCallbackContext& context) = 0;
virtual void updateMousePos(float x, float y) = 0;
virtual void updateMouseButton(bool isClicked) = 0;
virtual void updateMouseWheel(int direction) = 0;
Expand Down
6 changes: 3 additions & 3 deletions Framework/Core/src/runDataProcessing.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,8 @@ int runStateMachine(DataProcessorSpecs const& workflow,

DebugGUI* debugGUI = nullptr;
void* window = nullptr;
decltype(debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl)) debugGUICallback;
GuiCallbackContext guiContext;
decltype(debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl, guiContext)) debugGUICallback;

// An empty frameworkId means this is the driver, so we initialise the GUI
auto initDebugGUI = []() -> DebugGUI* {
Expand Down Expand Up @@ -1389,7 +1390,6 @@ int runStateMachine(DataProcessorSpecs const& workflow,
ServiceRegistryRef ref{serviceRegistry};
ref.registerService(ServiceRegistryHelpers::handleForService<DevicesManager>(devicesManager));

GuiCallbackContext guiContext;
guiContext.plugin = debugGUI;
guiContext.frameLast = uv_hrtime();
guiContext.frameLatency = &driverInfo.frameLatency;
Expand Down Expand Up @@ -1882,7 +1882,7 @@ int runStateMachine(DataProcessorSpecs const& workflow,
uv_timer_stop(gui_timer);
}

auto callback = debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl);
auto callback = debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl, guiContext);
guiContext.callback = [&serviceRegistry, &driverServices, &debugGUI, &infos, &runningWorkflow, &dataProcessorInfos, &metricsInfos, &driverInfo, &controls, &driverControl, callback]() {
callback();
for (auto& service : driverServices) {
Expand Down
110 changes: 75 additions & 35 deletions Framework/GUISupport/src/FrameworkGUIDebugger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "DebugGUI/imgui_extras.h"
#include "Framework/DriverControl.h"
#include "Framework/DriverInfo.h"
#include "Framework/GuiCallbackContext.h"
#include "Framework/DeviceMetricsHelper.h"
#include "Framework/DeviceMetricsInfo.h"
#include "FrameworkGUIDeviceInspector.h"
Expand Down Expand Up @@ -506,7 +507,7 @@ void displayDeviceMetrics(const char* label,
case MetricsDisplayStyle::Lines: {
auto xAxisFlags = ImPlotAxisFlags_None;
auto yAxisFlags = ImPlotAxisFlags_LockMin;
//ImPlot::FitNextPlotAxes(true, true, true, true);
// ImPlot::FitNextPlotAxes(true, true, true, true);
if (ImPlot::BeginPlot("##Some plot", {-1, -1}, axisFlags)) {
ImPlot::SetupAxes("time", "value", xAxisFlags, yAxisFlags);
ImPlot::SetupAxisFormat(ImAxis_Y1, formatSI, nullptr);
Expand Down Expand Up @@ -1008,6 +1009,71 @@ void popWindowColorDueToStatus()
ImGui::PopStyleVar(1);
}

int debugPID(int pid)
{
std::string pidStr = std::to_string(pid);
setenv("O2DEBUGGEDPID", pidStr.c_str(), 1);
#ifdef __APPLE__
std::string defaultAppleDebugCommand =
"osascript -e 'tell application \"Terminal\"'"
" -e 'activate'"
" -e 'do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'"
" -e 'end tell'";
setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0);
#else
setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0);
#endif
return system(getenv("O2DPLDEBUG"));
}

int profilePID(int pid)
{
std::string pidStr = std::to_string(pid);
setenv("O2PROFILEDPID", pidStr.c_str(), 1);
#ifdef __APPLE__
auto defaultAppleProfileCommand = fmt::format(
"osascript -e 'tell application \"Terminal\"'"
" -e 'activate'"
" -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
" --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} "
" && open dpl-profile-{0}.trace && exit\"'"
" -e 'end tell'",
pid);
std::cout << defaultAppleProfileCommand << std::endl;
setenv("O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
#else
setenv("O2DPLPROFILE", "xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0);
#endif
return system(getenv("O2DPLPROFILE"));
}

/// Show a window with the list of devices which have not yet exited
/// and provide a few controls to interact with them.
void displayShutdownDialog(std::vector<DeviceSpec> const& specs, std::vector<DeviceInfo> const& infos)
{
for (size_t i = 0; i < infos.size(); ++i) {
auto& info = infos[i];
if (info.active == false) {
continue;
}
auto& spec = specs[i];
ImGui::Text("Unable to quit due to the following devices:");
ImGui::Text("%s (%d).", spec.name.c_str(), info.pid);
ImGui::SameLine();
if (ImGui::Button("Force quit")) {
kill(info.pid, SIGKILL);
}
ImGui::SameLine();
if (ImGui::Button("Debug")) {
debugPID(info.pid);
}
ImGui::SameLine();
if (ImGui::Button("Profile")) {
profilePID(info.pid);
}
}
}

/// Display information window about the driver
/// and its state.
void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverControl)
Expand Down Expand Up @@ -1035,42 +1101,12 @@ void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverContro
}
ImGui::SameLine();
if (ImGui::Button("Debug driver")) {
std::string pidStr = std::to_string(pid);
setenv("O2DEBUGGEDPID", pidStr.c_str(), 1);
#ifdef __APPLE__
std::string defaultAppleDebugCommand =
"osascript -e 'tell application \"Terminal\"'"
" -e 'activate'"
" -e 'do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'"
" -e 'end tell'";
setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0);
#else
setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0);
#endif
int retVal = system(getenv("O2DPLDEBUG"));
(void)retVal;
debugPID(pid);
}

ImGui::SameLine();
if (ImGui::Button("Profile")) {
std::string pidStr = std::to_string(pid);
setenv("O2PROFILEDPID", pidStr.c_str(), 1);
#ifdef __APPLE__
auto defaultAppleProfileCommand = fmt::format(
"osascript -e 'tell application \"Terminal\"'"
" -e 'activate'"
" -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
" --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} "
" && open dpl-profile-{0}.trace && exit\"'"
" -e 'end tell'",
pid);
std::cout << defaultAppleProfileCommand << std::endl;
setenv("O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
#else
setenv("O2DPLPROFILE", "xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0);
#endif
int retVal = system(getenv("O2DPLPROFILE"));
(void)retVal;
profilePID(pid);
}

// FIXME: this should really be a combo box
Expand Down Expand Up @@ -1110,7 +1146,8 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos,
std::vector<DeviceMetricsInfo> const& metricsInfos,
DriverInfo const& driverInfo,
std::vector<DeviceControl>& controls,
DriverControl& driverControl)
DriverControl& driverControl,
GuiCallbackContext& gui)
{
static gui::WorkspaceGUIState globalGUIState;
gui::WorkspaceGUIState& guiState = globalGUIState;
Expand Down Expand Up @@ -1141,7 +1178,7 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos,
std::vector<TopologyNodeInfo> driverNodesInfos;
driverNodesInfos.push_back(TopologyNodeInfo{"driver"});

return [&infos, &devices, &allStates, &metadata, &controls, &metricsInfos, &driverInfo, &driverControl, deviceNodesInfos, driverNodesInfos]() {
return [&infos, &devices, &allStates, &metadata, &controls, &metricsInfos, &driverInfo, &driverControl, &gui, deviceNodesInfos, driverNodesInfos]() {
ImGuiStyle& style = ImGui::GetStyle();
style.FrameRounding = 0.;
style.WindowRounding = 0.;
Expand All @@ -1158,6 +1195,9 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos,
metricsStore.specs[DRIVER_METRICS] = gsl::span(driverNodesInfos);
displayMetrics(guiState, driverInfo, infos, metadata, controls, metricsStore);
displayDriverInfo(driverInfo, driverControl);
if (*(gui.guiQuitRequested) && !*(gui.allChildrenGone)) {
displayShutdownDialog(devices, infos);
}

int windowPosStepping = (ImGui::GetIO().DisplaySize.y - 500) / guiState.devices.size();

Expand Down
4 changes: 3 additions & 1 deletion Framework/GUISupport/src/FrameworkGUIDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace o2::framework

class DriverInfo;
class DriverControl;
class GuiCallbackContext;

namespace gui
{
Expand All @@ -37,7 +38,8 @@ std::function<void(void)> getGUIDebugger(std::vector<DeviceInfo> const& infos,
std::vector<DeviceMetricsInfo> const& metricsInfos,
DriverInfo const& driverInfo,
std::vector<DeviceControl>& controls,
DriverControl& driverControl);
DriverControl& driverControl,
GuiCallbackContext& context);

void updateMousePos(float x, float y);
void updateMouseButton(bool clicked);
Expand Down
5 changes: 3 additions & 2 deletions Framework/GUISupport/src/Plugin.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ struct ImGUIDebugGUI : o2::framework::DebugGUI {
std::vector<DeviceMetricsInfo> const& metricsInfos,
DriverInfo const& driverInfo,
std::vector<DeviceControl>& controls,
DriverControl& driverControl) override
DriverControl& driverControl,
GuiCallbackContext& context) override
{
return o2::framework::gui::getGUIDebugger(infos, devices, allStates, metadata, metricsInfos, driverInfo, controls, driverControl);
return o2::framework::gui::getGUIDebugger(infos, devices, allStates, metadata, metricsInfos, driverInfo, controls, driverControl, context);
}

void updateMousePos(float x, float y) override
Expand Down

0 comments on commit 7f758d4

Please sign in to comment.