[PATCH xf86-video-ati 6/7] Call drmHandleEvent again if it was interrupted by a signal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Michel Dänzer <michel.daenzer@xxxxxxx>

drmHandleEvent can be interrupted by a signal in read(), in which case
it doesn't process any events but returns -1, which
drm_handle_event propagated to its callers. This could cause the
following failure cascade:

1. drm_wait_pending_flip stopped waiting for a pending flip.
2. Its caller cleared drmmode_crtc->flip_pending before the flip
   completed.
3. Another flip was attempted but got an unexpected EBUSY error because
   the previous flip was still pending.
4. TearFree was disabled due to the error.

The solution is to call drmHandleEvent if it was interrupted by a
signal. We can do that in drm_handle_event, because when that is called,
either it is known that there are events ready to be processed, or the
caller has to wait for events to arrive anyway.

v2:
* Use ErrorF instead of xf86DrvMsg with hard-coded screen 0.

Bugzilla: https://bugs.freedesktop.org/109364
(Ported from amdgpu commit 3ff2cc225f6bc08364ee007fa54e9d0150adaf11)

Signed-off-by: Michel Dänzer <michel.daenzer@xxxxxxx>
---
 src/radeon_drm_queue.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index d8a8243c5..2e2b84040 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -30,6 +30,8 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
+
 #include <xorg-server.h>
 #include <X11/Xdefs.h>
 #include <list.h>
@@ -277,7 +279,20 @@ radeon_drm_handle_event(int fd, drmEventContext *event_context)
     struct radeon_drm_queue_entry *e;
     int r;
 
-    r = drmHandleEvent(fd, event_context);
+    /* Retry drmHandleEvent if it was interrupted by a signal in read() */
+    do {
+	r = drmHandleEvent(fd, event_context);
+    } while (r < 0 && (errno == EINTR || errno == EAGAIN));
+
+    if (r < 0) {
+	static Bool printed;
+
+	if (!printed) {
+	    ErrorF("%s: drmHandleEvent returned %d, errno=%d (%s)\n",
+		   __func__, r, errno, strerror(errno));
+	    printed = TRUE;
+	}
+    }
 
     while (!xorg_list_is_empty(&radeon_drm_flip_signalled)) {
 	e = xorg_list_first_entry(&radeon_drm_flip_signalled,
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/amd-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux