소스 검색

Fix a crash when an error happens inside a modal/live-resize draw.

Fixes #2179.
Sasha Szpakowski 2 달 전
부모
커밋
57d22d4c4d
3개의 변경된 파일25개의 추가작업 그리고 4개의 파일을 삭제
  1. 15 4
      src/modules/event/Event.cpp
  2. 1 0
      src/modules/event/Event.h
  3. 9 0
      src/modules/event/sdl/Event.cpp

+ 15 - 4
src/modules/event/Event.cpp

@@ -100,10 +100,21 @@ void Event::setDefaultModalDrawData(const ModalDrawData &data)
 
 
 void Event::modalDraw()
 void Event::modalDraw()
 {
 {
-	if (modalDrawData.draw != nullptr)
-		modalDrawData.draw(modalDrawData.context);
-	else if (defaultModalDrawData.draw != nullptr)
-		defaultModalDrawData.draw(defaultModalDrawData.context);
+	// Skip the draw if a previous one generated an unprocessed exception.
+	if (!deferredExceptionMessage.empty())
+		return;
+
+	try
+	{
+		if (modalDrawData.draw != nullptr)
+			modalDrawData.draw(modalDrawData.context);
+		else if (defaultModalDrawData.draw != nullptr)
+			defaultModalDrawData.draw(defaultModalDrawData.context);
+	}
+	catch (std::exception &e)
+	{
+		deferredExceptionMessage = e.what();
+	}
 }
 }
 
 
 } // event
 } // event

+ 1 - 0
src/modules/event/Event.h

@@ -86,6 +86,7 @@ protected:
 
 
 	ModalDrawData modalDrawData;
 	ModalDrawData modalDrawData;
 	ModalDrawData defaultModalDrawData;
 	ModalDrawData defaultModalDrawData;
+	std::string deferredExceptionMessage;
 
 
 	love::thread::MutexRef mutex;
 	love::thread::MutexRef mutex;
 	std::queue<Message *> queue;
 	std::queue<Message *> queue;

+ 9 - 0
src/modules/event/sdl/Event.cpp

@@ -167,6 +167,15 @@ void Event::pump(float waitTimeout)
 			// Fetch any extra events that came in during WaitEvent.
 			// Fetch any extra events that came in during WaitEvent.
 			shouldPoll = true;
 			shouldPoll = true;
 		}
 		}
+
+		// For exceptions generated inside a modal draw callback, propagate them
+		// outside of OS event processing instead of inside.
+		if (!deferredExceptionMessage.empty())
+		{
+			std::string exceptionstr = deferredExceptionMessage;
+			deferredExceptionMessage.clear();
+			throw love::Exception("%s", exceptionstr.c_str());
+		}
 	}
 	}
 
 
 	if (shouldPoll)
 	if (shouldPoll)