CAPI: Fix racy capi_read
capi_read still used interruptible_sleep_on, risking to miss a wakeup this way. Convert it to wait_event_interruptible. Signed-off-by: Jan Kiszka <jan.kiszka@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
54f0fad3d8
commit
28a1dbb6f7
@@ -657,24 +657,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
|||||||
struct capidev *cdev = (struct capidev *)file->private_data;
|
struct capidev *cdev = (struct capidev *)file->private_data;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
size_t copied;
|
size_t copied;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!cdev->ap.applid)
|
if (!cdev->ap.applid)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) {
|
skb = skb_dequeue(&cdev->recvqueue);
|
||||||
|
if (!skb) {
|
||||||
if (file->f_flags & O_NONBLOCK)
|
if (file->f_flags & O_NONBLOCK)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
err = wait_event_interruptible(cdev->recvwait,
|
||||||
for (;;) {
|
(skb = skb_dequeue(&cdev->recvqueue)));
|
||||||
interruptible_sleep_on(&cdev->recvwait);
|
if (err)
|
||||||
if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL)
|
return err;
|
||||||
break;
|
|
||||||
if (signal_pending(current))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (skb == NULL)
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
if (skb->len > count) {
|
if (skb->len > count) {
|
||||||
skb_queue_head(&cdev->recvqueue, skb);
|
skb_queue_head(&cdev->recvqueue, skb);
|
||||||
|
Reference in New Issue
Block a user