diff options
author | wtc%netscape.com <devnull@localhost> | 1999-04-02 23:21:08 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 1999-04-02 23:21:08 +0000 |
commit | 0cf2ea7d1b48c7c0fe6bd890ee7ccd3842b4fcf0 (patch) | |
tree | 1e45ebd2bb88891c4b2e533ac7fcec96e767642a | |
parent | ab19a5682cee8fe36ff7f2181c19d85c73eb71b6 (diff) | |
download | nspr-hg-0cf2ea7d1b48c7c0fe6bd890ee7ccd3842b4fcf0.tar.gz |
Made the i/o continuation thread ignore the events that have
been consumed by prior continuation function calls.
(Bugsplat bug #345296)
Modified files: primpl.h, ptio.c.
-rw-r--r-- | pr/include/private/primpl.h | 9 | ||||
-rw-r--r-- | pr/src/pthreads/ptio.c | 50 |
2 files changed, 51 insertions, 8 deletions
diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h index 10476e7c..92de7811 100644 --- a/pr/include/private/primpl.h +++ b/pr/include/private/primpl.h @@ -1462,6 +1462,15 @@ struct PRFilePrivate { PRInt32 state; PRBool nonblocking; PRBool inheritable; +#if defined(_PR_PTHREADS) + PRInt16 eventMask; /* A bitmask in which a 0 means + * the event should be ignored in + * the revents returned by poll. + * The eventMask field is only + * accessed by the i/o continuation + * thread. + */ +#endif PRFileDesc *next; PRIntn lockCount; _MDFileDesc md; diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c index d48b3a34..736e0e84 100644 --- a/pr/src/pthreads/ptio.c +++ b/pr/src/pthreads/ptio.c @@ -223,6 +223,7 @@ struct pt_Continuation /* These objects are linked in ascending timeout order */ pt_Continuation *next, *prev; /* self linked list of these things */ + PRFileDesc *fd; /* The building of the continuation operation */ ContinuationFn function; /* what function to continue */ union { PRIntn osfd; } arg1; /* #1 - the op's fd */ @@ -651,6 +652,7 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op) break; } PR_ASSERT((pt_Continuation*)-1 == pollingOps[pollingSlotsAllocated]); + op->fd->secret->eventMask = 0xffff; pollingOps[pollingListUsed] = op; pollingList[pollingListUsed].revents = 0; pollingList[pollingListUsed].fd = op->arg1.osfd; @@ -733,21 +735,42 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op) if (op == my_op) goto recycle; PR_Unlock(pt_tq.ml); } - else if ((0 != revents) - && (pt_continuation_pending == op->status) - && (op->function(op, revents))) + else if ((0 != (revents & op->fd->secret->eventMask)) + && (pt_continuation_pending == op->status)) { /* * Only good?(?) revents left. Operations not pending * will be pruned next time we build a list. This operation - * will be pruned if the continueation indicates it is + * will be pruned if the continuation indicates it is * finished. */ - PR_Lock(pt_tq.ml); - (void)pt_FinishTimedInternal(op); - if (op == my_op) goto recycle; - PR_Unlock(pt_tq.ml); + if (op->function(op, revents)) + { + PR_Lock(pt_tq.ml); + (void)pt_FinishTimedInternal(op); + if (op == my_op) goto recycle; + PR_Unlock(pt_tq.ml); + } + else + { + /* + * If the continuation function returns + * PR_FALSE, it means available data have + * been read, output buffer space has been + * filled, or pending connections have been + * accepted by prior calls. If the + * continuation function is immediately + * invoked again, it will most likely + * return PR_FALSE. So turn off these + * events in the event mask for this fd so + * that if this fd is encountered again in + * the polling list with these events on, + * we won't invoke the continuation + * function again. + */ + op->fd->secret->eventMask &= ~revents; + } } } } @@ -1299,6 +1322,7 @@ static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount) && (!fd->secret->nonblocking)) { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -1339,6 +1363,7 @@ static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) if (fNeedContinue == PR_TRUE) { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -1431,6 +1456,7 @@ static PRInt32 pt_Writev( /* so advance the description */ osiov->iov_base = (char*)osiov->iov_base + bytes; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)osiov; op.arg3.amount = osiov_len; @@ -1571,6 +1597,7 @@ static PRStatus pt_Connect( else { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; #ifdef _PR_HAVE_SOCKADDR_LEN op.arg2.buffer = (void*)&addrCopy; @@ -1645,6 +1672,7 @@ static PRFileDesc* pt_Accept( else { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = addr; op.arg3.addr_len = &addr_len; @@ -1787,6 +1815,7 @@ static PRInt32 pt_Recv( else { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -1866,6 +1895,7 @@ static PRInt32 pt_Send( if (fNeedContinue == PR_TRUE) { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -1920,6 +1950,7 @@ static PRInt32 pt_SendTo( if (fNeedContinue == PR_TRUE) { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -1965,6 +1996,7 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, if (fNeedContinue == PR_TRUE) { pt_Continuation op; + op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -2075,6 +2107,7 @@ static PRInt32 pt_AIXTransmitFile(PRFileDesc *sd, PRFileDesc *fd, if ((rv == 1) || ((rv == -1) && (count == 0))) { pt_Continuation op; + op.fd = sd; op.arg1.osfd = sd->secret->md.osfd; op.arg2.buffer = &sf_struct; op.arg4.flags = send_flags; @@ -2164,6 +2197,7 @@ static PRInt32 pt_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd, op.arg3.offset = count - hlen; } + op.fd = sd; op.arg1.osfd = sd->secret->md.osfd; op.filedesc = fd->secret->md.osfd; op.arg2.buffer = hdtrl; |