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