Fix BaseUI x-thread signal vs thread-start race

Control surfaces c'tor usually subscribe to signals e.g.
PortConnectedOrDisconnected. This happens after the parent BaseUI
is created, but before set_active() -> BaseUI::run() is called.

At this point in time there is no run_loop thread.

There are two options to handle AbstractUI::call_slot():

 A. Queue the event in the event-loop, using the thread-local
    request buffer of the caller. Then hope the BaseUI
    thread is started, and calls ::handle_ui_requests() before
    the memory pool runs out of space.

 B. Handle the event in the calling thread. -- This may not be
    rt-safe and may call functions with locks held by the caller.
    It will however not accumulate events.

This takes approach (B). If _run_loop_thread is NULL, directly
handle the signal.

In the past, prior to 50abcc74b5, approach (A) was taken.
NULL never matched Glib::Threads::Thread::self().

This also reverts a prior attempt (e417495505) to address this issue.
This commit is contained in:
Robin Gareus 2022-03-02 21:19:12 +01:00
parent 4fb8dd805f
commit 84c51a1411
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 2 additions and 3 deletions

View File

@ -119,12 +119,11 @@ BaseUI::run ()
m_context = MainContext::create();
_main_loop = MainLoop::create (m_context);
attach_request_source ();
Glib::Threads::Mutex::Lock lm (_run_lock);
_run_loop_thread = PBD::Thread::create (boost::bind (&BaseUI::main_thread, this));
_running.wait (_run_lock);
attach_request_source ();
}
void

View File

@ -53,7 +53,7 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
BaseUI* base_instance() { return base_ui_instance; }
Glib::RefPtr<Glib::MainLoop> main_loop() const { return _main_loop; }
bool caller_is_self () const { assert (_run_loop_thread); return _run_loop_thread->caller_is_self (); }
bool caller_is_self () const { return _run_loop_thread ? _run_loop_thread->caller_is_self () : true; }
bool ok() const { return _ok; }