STREAMS/UX for the HP 9000 Reference Manual
216
Debugging STREAMS/UX Modules and Drivers
Debugging Examples
For the sp driver, we found that spclose() calls freemsg():
static spclose(q)
queue_t *q;
{
struct sp *lp;
unsigned int s;
mblk_t *mp, *t_mp;
lp = (struct sp *) (q->q_ptr);
/* Free messages queued by spput() on interim mesg queue. */
s = splstr();
mp = lp->mp;
while (mp != NULL) {
t_mp = mp;
mp = mp->b_next;
freemsg(t_mp);
}
splx(s);
flushq(WR(q), 1);
q->q_ptr = NULL;
}
freemsg() is called to free all messages held in the interim message queue in
our private data area, but we do not zero out the pointers lp->mp or
lp->last_mp, which point to the head and tail of the private interim queue. A
call to sp_timeout() may still be pending in the timeout queue. When
sp_timeout() is executed, because lp->mp is non-NULL, it will call putq() to
pass lp->mp up to sp's read queue, where sp's service routine will call
putnext() to put it in lmodc's read queue. When flushq() is called on lmodc's
read queue, it tries to free this already freed message, causing a trap type 15
panic on the NULL b_datap. Adding the following code to spclose() will fix
this problem:
.
.
.
freemsg(t_mp);
}
splx(s);
/*
* NULL out list pointers to insure the messages they point to
* will not be freed twice.
*/
lp->mp = NULL;
lp->last_mp = NULL;
flushq(WR(q), 1);
q->q_ptr = NULL;
}