Debugging help

oliver (oliver@zeroknowledge.com)
Tue, 27 Jun 2000 14:05:40 -0400


Hi,

The following (somewhat ugly) code fragment is giving me a great deal of
trouble. After q great deal of debugging and looking at other blocking reads
in the kernel source, I can't seem to figure out what's going on. Perhaps
some kind chap out there in kernel land could give me a hint as to what
might be causing this:

The following blocking read call is snarfling packets that have been
intercepted in the kernel firewalling hooks, and sending them to user land.
The code works fine in most circumstances, but when an application reading
this device is debugged, it has a nasty tendancy to cause a deadlock. The
whole system falls to it's knees, interrupts stop working etc. The problem
seems to be related to signals being recieved inside the wait loop ... if I
change the function to never return -ERESTARTSYS, the problem seems to go
away.

Anyone have an idea as to what might be going on or where I should direct
my efforts? First born children offered by way of compensation...

Tia,
~ol

>>>>>>>>>>
static ssize_t
shim_read (struct file *file, char *buf, size_t count, loff_t *ppos)
{
ZkShimUnit *zun = (ZkShimUnit *) file->private_data;
struct wait_queue wait = { current, NULL };
int err;
size_t i = 0;
ZKMB_T *skb;

ZKDBG(5, "entered, count=%d\n", count);

/* Can't seek (pread) on this device */
if (ppos != &file->f_pos)
return -ESPIPE;

if(skb_queue_empty(&zun->zun_readq)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
add_wait_queue(&zun->zun_waitq, &wait);
repeat:
current->state = TASK_INTERRUPTIBLE;
if (skb_queue_empty(&zun->zun_readq) && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
remove_wait_queue(&zun->zun_waitq, &wait);
}

if(!skb_queue_empty(&zun->zun_readq) &&
(skb = skb_dequeue(&zun->zun_readq))) {
i = count;
if(i > skb->len)
i = skb->len;

skb->h.raw = skb->nh.raw;
err = skb_copy_datagram(skb, 0, buf, i);

kfree_skb(skb);

if (err) {
return err;
}
}

/* if i is replaced with count as the condition in this if
the problem vanishes, but the behaviour is wrong */
if (i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return i;
}

if (signal_pending(current))
return -ERESTARTSYS;

return 0;
} /* zkShimDevRead */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/