[PATCH] drm: fix drm_read() returning 0

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

 



Imagine two threads read()'ing on the drm file and both are asleep waiting
for events in drm_read(). If a single event occurs, both threads are woken
up and start fetching the event. One thread will get it and return, the
other thread will notice that there is no further event and return 0 to
user-space.

We can avoid this by waiting for events until we got at least one event or
an error occurred.

Signed-off-by: David Herrmann <dh.herrmann@xxxxxxxxxxxxxx>
---
The patch might look a bit scary but it adds only a single do { } while(!total);
around the whole block.

 drivers/gpu/drm/drm_fops.c |   33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 123de28..6e7d349 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -635,25 +635,26 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
 {
 	struct drm_file *file_priv = filp->private_data;
 	struct drm_pending_event *e;
-	size_t total;
+	size_t total = 0;
 	ssize_t ret;
 
-	ret = wait_event_interruptible(file_priv->event_wait,
-				       !list_empty(&file_priv->event_list));
-	if (ret < 0)
-		return ret;
-
-	total = 0;
-	while (drm_dequeue_event(file_priv, total, count, &e)) {
-		if (copy_to_user(buffer + total,
-				 e->event, e->event->length)) {
-			total = -EFAULT;
-			break;
-		}
+	do {
+		ret = wait_event_interruptible(file_priv->event_wait,
+					       !list_empty(&file_priv->event_list));
+		if (ret < 0)
+			return ret;
 
-		total += e->event->length;
-		e->destroy(e);
-	}
+		while (drm_dequeue_event(file_priv, total, count, &e)) {
+			if (copy_to_user(buffer + total,
+					 e->event, e->event->length)) {
+				total = -EFAULT;
+				break;
+			}
+
+			total += e->event->length;
+			e->destroy(e);
+		}
+	} while (!total);
 
 	return total;
 }
-- 
1.7.10.4

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel


[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux