mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-04 08:46:09 +00:00
Fix crash on Windows using Manager::enqueueMessage() from non-UI thread
From time to time the app::BackupObserver::backgroundThread() will use ui::execute_from_ui_thread() to show/hide the backup notification icon in the StatusBar (see SwitchBackupIcon class). This ui::execute_from_ui_thread() function enqueues a ui::FunctionMessage calling the Manager::enqueueMessage(). The issue here is that enqueueMessage() uses ui::is_ui_thread() to check if the thread that wants to enqueue the message is the UI thread or other thread, and depending on this decission the message will be directly added to msg_queue or enqueued into concurrent_msg_queue. The issue was that ui::is_ui_thread() was not working correctly on Windows because GetCurrentThread() is not useful to check the current thread with a previous call of GetCurrentThread() from other thread (the function always return the same value, a special generic value that identifies the current thread whatever it is).
This commit is contained in:
parent
2eba51a62d
commit
38abac8b79
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 50eb8e89d69ab471f73deb17a096e8b037c3bb9c
|
||||
Subproject commit f81220824324b75ec52ad7aae3d23d0610bd8144
|
@ -78,7 +78,7 @@ Manager* Manager::m_defaultManager = NULL;
|
||||
gfx::Region Manager::m_dirtyRegion;
|
||||
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
static base::thread::native_handle_type manager_thread = 0;
|
||||
static base::thread::native_id_type manager_thread = 0;
|
||||
#endif
|
||||
|
||||
static WidgetsList mouse_widgets_list; // List of widgets to send mouse events
|
||||
@ -168,7 +168,7 @@ Manager::Manager()
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(!manager_thread);
|
||||
manager_thread = base::this_thread::native_handle();
|
||||
manager_thread = base::this_thread::native_id();
|
||||
#endif
|
||||
|
||||
if (!m_defaultManager) {
|
||||
@ -195,7 +195,7 @@ Manager::Manager()
|
||||
Manager::~Manager()
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
// There are some messages in queue? Dispatch everything.
|
||||
@ -277,6 +277,10 @@ void Manager::flipDisplay()
|
||||
|
||||
bool Manager::generateMessages()
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
// First check: there are windows to manage?
|
||||
if (children().empty())
|
||||
return false;
|
||||
@ -337,6 +341,10 @@ static MouseButtons mouse_buttons_from_os_to_ui(const os::Event& sheEvent)
|
||||
|
||||
void Manager::generateMessagesFromOSEvents()
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
os::Event lastMouseMoveEvent;
|
||||
|
||||
// Events from "she" layer.
|
||||
@ -701,6 +709,7 @@ void Manager::dispatchMessages()
|
||||
|
||||
void Manager::addToGarbage(Widget* widget)
|
||||
{
|
||||
ASSERT(widget);
|
||||
m_garbage.push_back(widget);
|
||||
}
|
||||
|
||||
@ -909,7 +918,7 @@ void Manager::freeCapture()
|
||||
void Manager::freeWidget(Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
if (widget->hasFocus() || (widget == focus_widget))
|
||||
@ -940,7 +949,7 @@ void Manager::freeWidget(Widget* widget)
|
||||
void Manager::removeMessagesFor(Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
for (Message* msg : msg_queue)
|
||||
@ -953,7 +962,7 @@ void Manager::removeMessagesFor(Widget* widget)
|
||||
void Manager::removeMessagesFor(Widget* widget, MessageType type)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
for (Message* msg : msg_queue)
|
||||
@ -968,7 +977,7 @@ void Manager::removeMessagesFor(Widget* widget, MessageType type)
|
||||
void Manager::removeMessagesForTimer(Timer* timer)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
for (auto it=msg_queue.begin(); it != msg_queue.end(); ) {
|
||||
@ -986,7 +995,7 @@ void Manager::removeMessagesForTimer(Timer* timer)
|
||||
void Manager::addMessageFilter(int message, Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
LockFilters lock;
|
||||
@ -1000,7 +1009,7 @@ void Manager::addMessageFilter(int message, Widget* widget)
|
||||
void Manager::removeMessageFilter(int message, Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
LockFilters lock;
|
||||
@ -1018,7 +1027,7 @@ void Manager::removeMessageFilter(int message, Widget* widget)
|
||||
void Manager::removeMessageFilterFor(Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
LockFilters lock;
|
||||
@ -1341,6 +1350,10 @@ void Manager::onSizeHint(SizeHintEvent& ev)
|
||||
|
||||
int Manager::pumpQueue()
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
#ifdef LIMIT_DISPATCH_TIME
|
||||
base::tick_t t = base::current_tick();
|
||||
#endif
|
||||
@ -1355,6 +1368,7 @@ int Manager::pumpQueue()
|
||||
// The message to process
|
||||
auto it = msg_queue.begin();
|
||||
Message* msg = *it;
|
||||
ASSERT(msg);
|
||||
|
||||
// Move the message from msg_queue to used_msg_queue
|
||||
msg_queue.erase(it);
|
||||
@ -1410,7 +1424,7 @@ int Manager::pumpQueue()
|
||||
bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
|
||||
{
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(manager_thread == base::this_thread::native_handle());
|
||||
ASSERT(manager_thread == base::this_thread::native_id());
|
||||
#endif
|
||||
|
||||
if (!widget)
|
||||
|
@ -32,7 +32,7 @@ namespace ui {
|
||||
|
||||
// This is used to check if calls to UI layer are made from the non-UI
|
||||
// thread. (Which might be catastrofic.)
|
||||
base::thread::native_handle_type main_gui_thread;
|
||||
base::thread::native_id_type main_gui_thread;
|
||||
|
||||
// Current mouse cursor type.
|
||||
|
||||
@ -188,7 +188,7 @@ UISystem::UISystem()
|
||||
ASSERT(!g_instance);
|
||||
g_instance = this;
|
||||
|
||||
main_gui_thread = base::this_thread::native_handle();
|
||||
main_gui_thread = base::this_thread::native_id();
|
||||
mouse_cursor_type = kOutsideDisplay;
|
||||
support_native_custom_cursor =
|
||||
((os::instance() &&
|
||||
@ -362,7 +362,7 @@ void execute_from_ui_thread(std::function<void()>&& f)
|
||||
|
||||
bool is_ui_thread()
|
||||
{
|
||||
return (main_gui_thread == base::this_thread::native_handle());
|
||||
return (main_gui_thread == base::this_thread::native_id());
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user