BugFix: correctly wait for Mixer to save file on exit

On the way, also improved Connection Manager ending properly.
This commit is contained in:
Bruno
2022-01-17 19:45:58 +01:00
parent 81e8d6d99c
commit 0b4d273e08
7 changed files with 99 additions and 86 deletions

View File

@@ -35,16 +35,12 @@
#endif
Connection::Connection() : receiver_(nullptr)
Connection::Connection() : asking_(false), receiver_(nullptr)
{
}
Connection::~Connection()
{
if (receiver_!=nullptr) {
receiver_->Break();
delete receiver_;
}
}
bool Connection::init()
@@ -52,6 +48,7 @@ bool Connection::init()
// add default info for myself
connections_.push_back(ConnectionInfo());
if (receiver_ == nullptr) {
// try to open a socket at base handshake port
int trial = 0;
while (trial < MAX_HANDSHAKE) {
@@ -79,12 +76,15 @@ bool Connection::init()
// try again
trial++;
}
}
// perfect, we could initialize the receiver
if (receiver_!=nullptr) {
// listen for answers
std::thread(listen).detach();
// regularly check for available streaming hosts
asking_ = true;
std::thread(ask).detach();
// inform the application settings of our id
@@ -104,10 +104,31 @@ bool Connection::init()
void Connection::terminate()
{
if (receiver_!=nullptr)
// end ask loop
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
asking_ = false;
if ( ask_end_.wait_for(lck,std::chrono::seconds(2)) == std::cv_status::timeout)
g_printerr("Failed to terminate Connection manager (asker).");
// end receiver
if (receiver_!=nullptr) {
// request termination of receiver
receiver_->AsynchronousBreak();
// restore state of Streamer
// wait for the listenner end notification
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
if ( listen_end_.wait_for(lck,std::chrono::seconds(2)) == std::cv_status::timeout)
g_printerr("Failed to terminate Connection manager (listener).");
// delete receiver and ready to initialize
delete receiver_;
receiver_ = nullptr;
}
// end Streamers
Streaming::manager().enable( false );
}
@@ -175,6 +196,8 @@ void Connection::listen()
#endif
if (Connection::manager().receiver_)
Connection::manager().receiver_->Run();
Connection::manager().listen_end_.notify_all();
}
void Connection::ask()
@@ -191,7 +214,7 @@ void Connection::ask()
socket.SetEnableBroadcast(true);
// loop infinitely
while(true)
while(Connection::manager().asking_)
{
// broadcast on several ports
for(int i=HANDSHAKE_PORT; i<HANDSHAKE_PORT+MAX_HANDSHAKE; i++)
@@ -208,7 +231,7 @@ void Connection::ask()
// erase connection if its life score is negative (not responding too many times)
if ( (*it).alive < 0 ) {
// inform streamer to cancel streaming to this client
Streaming::manager().removeStreams( (*it).name );
// Streaming::manager().removeStreams( (*it).name );
// remove from list
it = Connection::manager().connections_.erase(it);
#ifdef CONNECTION_DEBUG
@@ -222,6 +245,7 @@ void Connection::ask()
}
}
Connection::manager().ask_end_.notify_all();
}
void Connection::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,

View File

@@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include <condition_variable>
#include "NetworkToolkit.h"
@@ -86,8 +87,11 @@ protected:
private:
static void ask();
std::atomic<bool> asking_;
std::condition_variable ask_end_;
static void listen();
RequestListener listener_;
std::condition_variable listen_end_;
UdpListeningReceiveSocket *receiver_;
std::vector< ConnectionInfo > connections_;

View File

@@ -105,11 +105,11 @@ void Mixer::update()
// get the session loaded by this loader
merge( sessionImporters_.back().get() );
// FIXME: shouldn't we delete the imported session?
}
// done with this session loader
sessionImporters_.pop_back();
}
}
}
// if there is a session loader pending
if (!sessionLoaders_.empty()) {
@@ -119,9 +119,9 @@ void Mixer::update()
if (sessionLoaders_.back().valid()) {
// get the session loaded by this loader
set( sessionLoaders_.back().get() );
}
// done with this session loader
sessionLoaders_.pop_back();
}
busy_ = false;
}
}
@@ -135,9 +135,9 @@ void Mixer::update()
// did we get a filename in return?
if (sessionSavers_.back().valid()) {
filename = sessionSavers_.back().get();
}
// done with this session saver
sessionSavers_.pop_back();
}
if (filename.empty())
Log::Warning("Failed to save Session.");
// all ok

View File

@@ -118,11 +118,12 @@ bool Streaming::busy()
{
bool b = false;
streamers_lock_.lock();
if (streamers_lock_.try_lock()) {
std::vector<VideoStreamer *>::const_iterator sit = streamers_.begin();
for (; sit != streamers_.end() && !b; ++sit)
b = (*sit)->busy() ;
streamers_lock_.unlock();
}
return b;
}
@@ -132,11 +133,12 @@ std::vector<std::string> Streaming::listStreams()
{
std::vector<std::string> ls;
streamers_lock_.lock();
if (streamers_lock_.try_lock()) {
std::vector<VideoStreamer *>::const_iterator sit = streamers_.begin();
for (; sit != streamers_.end(); ++sit)
ls.push_back( (*sit)->info() );
streamers_lock_.unlock();
}
return ls;
}

View File

@@ -141,7 +141,6 @@ UserInterface::UserInterface()
currentTextEdit.clear();
screenshot_step = 0;
pending_save_on_exit = false;
close_and_exit = false;
sessionopendialog = nullptr;
sessionimportdialog = nullptr;
@@ -154,7 +153,6 @@ bool UserInterface::Init()
return false;
pending_save_on_exit = false;
close_and_exit = false;
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
@@ -685,28 +683,24 @@ bool UserInterface::TryClose()
if (DialogToolkit::FileDialog::busy())
return false;
// force close if trying to close again although it is already pending for save
if (pending_save_on_exit) {
close_and_exit = true;
return true;
}
// determine if a pending save of session is required
pending_save_on_exit = ( Settings::application.recentSessions.save_on_exit
&& !Mixer::manager().session()->empty()
&& Mixer::manager().session()->filename().empty() );
// if no pending save of session is needed, close
if (!pending_save_on_exit)
{
// stop all recordings
// always stop all recordings
FrameGrabbing::manager().stopAll();
// save on exit
if (Settings::application.recentSessions.save_on_exit)
Mixer::manager().save(false);
// force close if trying to close again although it is already pending for save
if (pending_save_on_exit)
return true;
close_and_exit = true;
// save on exit
pending_save_on_exit = false;
if (Settings::application.recentSessions.save_on_exit && !Mixer::manager().session()->empty())
{
// determine if a pending save of session is required
if (Mixer::manager().session()->filename().empty())
// need to wait for user to give a filename
pending_save_on_exit = true;
else
// ok to save the session
Mixer::manager().save(false);
}
// say we can close if no pending save of session is needed
@@ -784,8 +778,7 @@ void UserInterface::NewFrame()
ImGui::CloseCurrentPopup();
}
if (ImGui::Button(MENU_QUIT, ImVec2(ImGui::GetWindowContentRegionWidth(), 0))) {
pending_save_on_exit = false;
close_and_exit = true;
Rendering::manager().close();
ImGui::CloseCurrentPopup();
}
ImGui::Spacing();
@@ -793,21 +786,6 @@ void UserInterface::NewFrame()
}
}
// Asked to close_and_exit
if (close_and_exit){
if (!ImGui::IsPopupOpen("Closing"))
ImGui::OpenPopup("Closing");
if (ImGui::BeginPopupModal("Closing", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Please wait...");
ImGui::EndPopup();
}
// exit only after everything is closed
if (!FrameGrabbing::manager().busy() && !Mixer::manager().busy()) {
Rendering::manager().close();
}
}
// navigator bar first
navigator.Render();
}

View File

@@ -405,7 +405,6 @@ protected:
int target_view_navigator;
unsigned int screenshot_step;
bool pending_save_on_exit;
bool close_and_exit;
// Dialogs
DialogToolkit::OpenSessionDialog *sessionopendialog;

View File

@@ -162,6 +162,12 @@ int main(int argc, char *argv[])
///
UserInterface::manager().Terminate();
///
/// MIXER TERMINATE
///
while (Mixer::manager().busy())
Mixer::manager().update();
///
/// RENDERING TERMINATE
///