diff options
author | Jan Kiszka <jan.kiszka@web.de> | 2010-02-08 05:12:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-16 19:01:25 -0500 |
commit | 28a1dbb6f7feade304f43798feb15f6978516624 (patch) | |
tree | d21dbbcfa1d9a4ed76ad982cc57970e2eeb966f8 | |
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>
-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) | |||
657 | struct capidev *cdev = (struct capidev *)file->private_data; | 657 | struct capidev *cdev = (struct capidev *)file->private_data; |
658 | struct sk_buff *skb; | 658 | struct sk_buff *skb; |
659 | size_t copied; | 659 | size_t copied; |
660 | int err; | ||
660 | 661 | ||
661 | if (!cdev->ap.applid) | 662 | if (!cdev->ap.applid) |
662 | return -ENODEV; | 663 | return -ENODEV; |
663 | 664 | ||
664 | if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) { | 665 | skb = skb_dequeue(&cdev->recvqueue); |
665 | 666 | if (!skb) { | |
666 | if (file->f_flags & O_NONBLOCK) | 667 | if (file->f_flags & O_NONBLOCK) |
667 | return -EAGAIN; | 668 | return -EAGAIN; |
668 | 669 | err = wait_event_interruptible(cdev->recvwait, | |
669 | for (;;) { | 670 | (skb = skb_dequeue(&cdev->recvqueue))); |
670 | interruptible_sleep_on(&cdev->recvwait); | 671 | if (err) |
671 | if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL) | 672 | return err; |
672 | break; | ||
673 | if (signal_pending(current)) | ||
674 | break; | ||
675 | } | ||
676 | if (skb == NULL) | ||
677 | return -ERESTARTNOHAND; | ||
678 | } | 673 | } |
679 | if (skb->len > count) { | 674 | if (skb->len > count) { |
680 | skb_queue_head(&cdev->recvqueue, skb); | 675 | skb_queue_head(&cdev->recvqueue, skb); |