From fdf8e1a9bf9a9733c91159c6979c1cd138463db5 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Wed, 25 Feb 2015 11:42:38 +0000
Subject: [PATCH] Fix deadlock on vstatlock.

When a resize event is serviced, cache the new scaling factor.  Next time
the event queue is empty, attempt to lock vstatlock.  If that succeeds,
apply the new scaling.  If not, wait for the queue to drain again.

This may cause the scaling to be slightly delayed, but should completely
solve this deadlock.

This deadlock likely never affected FreeBSD since FreeBSD has deadlock
detection, and the return value of pthread_mutex_lock() isn't tested.  The
result would have been a silent failure to lock, and an update of the scaling
factor regardless, followed by a silent (again untested) failure of the matching
pthread_mutex_unlock() call.
---
 src/conio/sdl_con.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index f4dd80fd22..4bab1c1f2a 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -1459,6 +1459,7 @@ int win_to_text_ypos(int winpos)
 int sdl_video_event_thread(void *data)
 {
 	SDL_Event	ev;
+	int			new_scaling = -1;
 
 	if(!init_sdl_video()) {
 		char	driver[16];
@@ -1480,8 +1481,19 @@ int sdl_video_event_thread(void *data)
 		}
 
 		while(1) {
-			if(sdl.PollEvent(&ev)!=1)
+			if(sdl.PollEvent(&ev)!=1) {
+				if (new_scaling != -1) {
+					if (pthread_mutex_trylock(&vstatlock) == 0) {
+						vstat.scaling=new_scaling;
+						new_scaling = -1;
+						if(vstat.scaling < 1)
+							vstat.scaling=1;
+						pthread_mutex_unlock(&vstatlock);
+						setup_surfaces();
+					}
+				}
 				SLEEP(1);
+			}
 			else {
 				switch (ev.type) {
 					case SDL_ACTIVEEVENT:		/* Focus change */
@@ -1538,16 +1550,8 @@ int sdl_video_event_thread(void *data)
 								yuv.win_width=ev.resize.w;
 								yuv.win_height=ev.resize.h;
 							}
-							else {
-								if (vstat.scaling!=(int)(ev.resize.w/(vstat.charwidth*vstat.cols))) {
-									pthread_mutex_lock(&vstatlock);
-									vstat.scaling=(int)(ev.resize.w/(vstat.charwidth*vstat.cols));
-									if(vstat.scaling < 1)
-										vstat.scaling=1;
-									pthread_mutex_unlock(&vstatlock);
-								}
-							}
-							setup_surfaces();
+							else
+								new_scaling = (int)(ev.resize.w/(vstat.charwidth*vstat.cols));
 						}
 						break;
 					case SDL_VIDEOEXPOSE:
-- 
GitLab