From 9a18326aecd53c5619109dd2c5da1f26689f2f7b Mon Sep 17 00:00:00 2001 From: yum Date: Sat, 9 Sep 2023 17:00:36 -0700 Subject: Bugfix: fix process leak in PythonWrapper::InvokeCommandWithArgs It now waits up to 10 seconds for a graceful exit and falls back on the equivalent of a SIGKILL. The caller is assumed to have signaled to the process through `in_cb` that an exit is desired. Also: * Fix graceful exit path of transcribe_v2.py. * Add toggle to enable/disable preview text. It is enabled by default. * Constrain transcription temperature to 0.0. This keeps latency more predictable at the cost of some accuracy. --- GUI/GUI/GUI/Config.cpp | 3 +++ GUI/GUI/GUI/Config.h | 1 + GUI/GUI/GUI/Frame.cpp | 32 ++++++++++++++++++++++++++++---- GUI/GUI/GUI/Frame.h | 1 + GUI/GUI/GUI/PythonWrapper.cpp | 11 ++++++++++- 5 files changed, 43 insertions(+), 5 deletions(-) (limited to 'GUI') diff --git a/GUI/GUI/GUI/Config.cpp b/GUI/GUI/GUI/Config.cpp index 456f5d4..db4b184 100644 --- a/GUI/GUI/GUI/Config.cpp +++ b/GUI/GUI/GUI/Config.cpp @@ -82,6 +82,7 @@ AppConfig::AppConfig(wxTextCtrl* out) enable_profanity_filter(false), enable_debug_mode(false), reset_on_toggle(true), + enable_previews(true), gpu_idx(0), keybind("ctrl+x"), @@ -122,6 +123,7 @@ bool AppConfig::Serialize(const std::filesystem::path& path) { cm.Set("enable_profanity_filter", enable_profanity_filter); cm.Set("enable_debug_mode", enable_debug_mode); cm.Set("reset_on_toggle", reset_on_toggle); + cm.Set("enable_previews", enable_previews); cm.Set("gpu_idx", gpu_idx); cm.Set("keybind", keybind); @@ -175,6 +177,7 @@ bool AppConfig::Deserialize(const std::filesystem::path& path) { cm.Get("enable_profanity_filter", c.enable_profanity_filter); cm.Get("enable_debug_mode", c.enable_debug_mode); cm.Get("reset_on_toggle", c.reset_on_toggle); + cm.Get("enable_previews", c.enable_previews); cm.Get("gpu_idx", c.gpu_idx); cm.Get("keybind", c.keybind); diff --git a/GUI/GUI/GUI/Config.h b/GUI/GUI/GUI/Config.h index a6f83e2..4137c59 100644 --- a/GUI/GUI/GUI/Config.h +++ b/GUI/GUI/GUI/Config.h @@ -68,6 +68,7 @@ public: bool enable_profanity_filter; bool enable_debug_mode; bool reset_on_toggle; + bool enable_previews; int gpu_idx; std::string keybind; diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp index 9a781e8..2823437 100644 --- a/GUI/GUI/GUI/Frame.cpp +++ b/GUI/GUI/GUI/Frame.cpp @@ -70,6 +70,7 @@ namespace { ID_PY_APP_ENABLE_PROFANITY_FILTER, ID_PY_APP_ENABLE_DEBUG_MODE, ID_PY_APP_RESET_ON_TOGGLE, + ID_PY_APP_ENABLE_PREVIEWS, ID_PY_APP_ROWS, ID_PY_APP_COLS, ID_PY_APP_GPU_IDX, @@ -942,6 +943,17 @@ Frame::Frame() ); py_app_reset_on_toggle_ = py_app_reset_on_toggle; + auto* py_app_enable_previews = new wxCheckBox(py_config_panel, + ID_PY_APP_ENABLE_PREVIEWS, "Enable previews"); + py_app_enable_previews->SetValue(app_c_->enable_previews); + py_app_enable_previews->SetToolTip( + "If checked, audio that has not yet stabilized will also " + "be transcribed and shown. Turn this off if you're on a " + "resource-constrained system or if transcription is " + "running slowly." + ); + py_app_enable_previews_ = py_app_enable_previews; + // Hack: Add newlines before and after the button text to make // the buttons bigger, and easier to click from inside VR. auto* py_app_start_button = new wxButton(py_config_panel, @@ -957,6 +969,8 @@ Frame::Frame() /*flags=*/wxEXPAND); sizer->Add(py_app_reset_on_toggle, /*proportion=*/0, /*flags=*/wxEXPAND); + sizer->Add(py_app_enable_previews, /*proportion=*/0, + /*flags=*/wxEXPAND); sizer->Add(py_app_enable_browser_src, /*proportion=*/0, /*flags=*/wxEXPAND); sizer->Add(py_app_enable_local_beep, /*proportion=*/0, @@ -1538,6 +1552,9 @@ void Frame::ApplyConfigToInputFields() auto* py_app_reset_on_toggle = static_cast(FindWindowById(ID_PY_APP_RESET_ON_TOGGLE)); py_app_reset_on_toggle->SetValue(app_c_->reset_on_toggle); + auto* py_app_enable_previews = static_cast(FindWindowById(ID_PY_APP_ENABLE_PREVIEWS)); + py_app_enable_previews->SetValue(app_c_->enable_previews); + // Unity panel auto* unity_assets_path = static_cast(FindWindowById(ID_UNITY_ASSETS_FILE_PICKER)); unity_assets_path->SetPath(app_c_->assets_path); @@ -1574,7 +1591,6 @@ void Frame::OnExit(wxCloseEvent& event) { OnAppStop(); OnUnityAutoRefreshStop(); - // Allow default close processing to continue. event.Skip(); } @@ -2245,6 +2261,7 @@ void Frame::OnAppStart(wxCommandEvent& event) { const bool enable_profanity_filter = py_app_enable_profanity_filter_->GetValue(); const bool enable_debug_mode = py_app_enable_debug_mode_->GetValue(); const bool reset_on_toggle = py_app_reset_on_toggle_->GetValue(); + const bool enable_previews = py_app_enable_previews_->GetValue(); ASSIGN_OR_RETURN_VOID(int, rows, stoiInRange(transcribe_out_, py_app_rows_->GetValue().ToStdString(), "rows", 1, 10)); ASSIGN_OR_RETURN_VOID(int, cols, stoiInRange(transcribe_out_, py_app_cols_->GetValue().ToStdString(), "cols", 1, 120)); @@ -2277,6 +2294,7 @@ void Frame::OnAppStart(wxCommandEvent& event) { app_c_->enable_profanity_filter = enable_profanity_filter; app_c_->enable_debug_mode = enable_debug_mode; app_c_->reset_on_toggle = reset_on_toggle; + app_c_->enable_previews = enable_previews; app_c_->gpu_idx = gpu_idx; app_c_->keybind = keybind; app_c_->Serialize(AppConfig::kConfigPath); @@ -2306,7 +2324,13 @@ void Frame::OnAppStart(wxCommandEvent& event) { } } }; - auto in_cb = [&](std::string& in) {}; + auto in_cb = [&](std::string& in) { + if (!run_py_app_) { + std::ostringstream oss; + oss << "exit" << std::endl; + in = oss.str(); + } + }; auto run_cb = [&]() { return run_py_app_; }; @@ -2338,7 +2362,7 @@ void Frame::OnAppStop() { } else { py_app_.wait(); - Log(transcribe_out_, "Stopped transcription engine\n"); + Log(transcribe_out_, "Stopped transcription engine\n"); } status = obs_app_.wait_for(std::chrono::seconds(0)); if (status == std::future_status::ready) { @@ -2346,7 +2370,7 @@ void Frame::OnAppStop() { } else { obs_app_.wait(); - Log(transcribe_out_, "Stopped browser source\n"); + Log(transcribe_out_, "Stopped browser source\n"); } transcript_.Clear(); } diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h index 2a538b4..7baf77f 100644 --- a/GUI/GUI/GUI/Frame.h +++ b/GUI/GUI/GUI/Frame.h @@ -72,6 +72,7 @@ private: wxCheckBox* py_app_enable_profanity_filter_; wxCheckBox* py_app_enable_debug_mode_; wxCheckBox* py_app_reset_on_toggle_; + wxCheckBox* py_app_enable_previews_; wxCheckBox* unity_clear_osc_; wxCheckBox* unity_enable_phonemes_; diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index 7141037..29b7d75 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -320,7 +320,16 @@ bool PythonWrapper::InvokeCommandWithArgs(const std::string& cmd, } } if (!run_cb()) { - return false; + DWORD timeout_ms = 1000 * 10; + DWORD ret = WaitForSingleObject(pi.hProcess, timeout_ms); + + if (ret == WAIT_TIMEOUT) { + std::ostringstream stderr_oss; + stderr_oss << "Timed out waiting for graceful exit, killing process"; + out_cb("", stderr_oss.str()); + + TerminateProcess(pi.hProcess, 0); + } } std::ostringstream stdout_oss, stderr_oss; -- cgit v1.2.3