diff options
author | Jan Kiszka | 2010-02-08 10:12:21 +0000 |
---|---|---|
committer | David S. Miller | 2010-02-16 16:01:25 -0800 |
commit | 28a1dbb6f7feade304f43798feb15f6978516624 (patch) | |
tree | d21dbbcfa1d9a4ed76ad982cc57970e2eeb966f8 /drivers/isdn | |
parent | 54f0fad3d8414cf770c1cf25a1d98fcaec899b5a (diff) |
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>
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/capi/capi.c | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index f8f86602c57e..8abec9655e1a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -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 sk_buff *skb; size_t copied; + int err; if (!cdev->ap.applid) return -ENODEV; - if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) { - + skb = skb_dequeue(&cdev->recvqueue); + if (!skb) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; - - for (;;) { - interruptible_sleep_on(&cdev->recvwait); - if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL) - break; - if (signal_pending(current)) - break; - } - if (skb == NULL) - return -ERESTARTNOHAND; + err = wait_event_interruptible(cdev->recvwait, + (skb = skb_dequeue(&cdev->recvqueue))); + if (err) + return err; } if (skb->len > count) { skb_queue_head(&cdev->recvqueue, skb); |