mirror of https://github.com/aseprite/aseprite.git
				
				
				
			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