Problem interrupting threads in PR_Accept() wiht PR_Interrupt()
Joachim Ziegler <[email protected]>
| Newsgroups | gmane.comp.mozilla.devel.nspr |
|---|---|
| Message-ID | <[email protected]> |
Hello,
to get familiarized with NSPR, I have written a little demo web server.
The server has master thread that creates 5 worker threads. Each worker
thread blocks in PR_Accept() to wait for a new request, then serves the
request, the goes on in an endless loop. This loop looks like this:
while( 1 ) {
if((fd = PR_Accept( sock, NULL, PR_INTERVAL_NO_TIMEOUT ))
== NULL) {
if(PR_GetError() == PR_PENDING_INTERRUPT_ERROR)
break; /* that's OK: master has signaled an interrupt */
else {
oops("PR_Accept in thread_start()");
continue;
}
}
handle_call( fd );
PR_Close( fd );
}
/* this line should be reached on a clean shutdown*/
printf("\t[%d] Thread %d is shutting down.\n",
myPID, nthread);
Now I want to signal the worker threads to properly shut down, that is,
to break out of the loop. I do this by making the master thread issue
for(nthread = 0; nthread < NTHREADS; nthread++)
if( PR_Interrupt(worker[nthread]) == PR_SUCCESS )
printf("MASTER[%d]: Thread %d is blocked. Sent PR_Interrupt.\n",
myPID, nthread);
else
printf("MASTER[%d]: Thread %d is not blocked. Sent PR_Interrupt\n",
myPID, nthread);
This works fine when the server is not busy, that is, when all worker
threads are blocking in PR_Accept().
But when I force the server under a heavy load (e.g., by making 100
parallel requests to it) then somehow some interrupt signals seem to get
lost: Some worker threads unblock from PR_Accept() with fd != 0 (which
is OK as long as there are requests). After, however, all requests have
been served, they still block in PR_Accept(). This means that the
interrupt signals are lost.
The reference page says:
http://www.mozilla.org/projects/nspr/reference/html/prthrd.html#15471
"The interrupt request remains in the thread's state until it is
delivered exactly once or explicitly canceled."
(By "canceled", the page probably means a call to PR_ClearInterrupt();
if so, it should be changed to "cleared" on this page.)
So the requests must still be there in the thread's state, but the
thread does not unblock from PR_Accept().
What am I doing wrong here?
Here is a little logging output. 24826 is the PID. As you can see,
thread 3 does not get the interrupt signal, and thread 4, though
terminated, is never joined (the master joins with its workers after
issuing the PR_Interrupt()). Thread 3 keeps on PR_Accept()ing requests.
[...]
[24826] Thread 2 got request: GET /www/bigfile.html HTTP/1.0
[24826] Thread 3 got request: GET /www/bigfile.html HTTP/1.0
MASTER[24826]: Sending interrupt signal to worker threads.
MASTER[24826]: Thread 0 is blocked. Sent PR_Interrupt.
MASTER[24826]: Thread 1 is blocked. Sent PR_Interrupt.
MASTER[24826]: Thread 2 is blocked. Sent PR_Interrupt.
MASTER[24826]: Thread 3 is blocked. Sent PR_Interrupt.
MASTER[24826]: Thread 4 is blocked. Sent PR_Interrupt.
MASTER[24826]: Joining worker threads.
oops: PR_TransmitFile in do_cat: -5993
[24826] Thread 1 is shutting down.
[24826] Thread 0 is shutting down.
MASTER[24826]: Thread 0 successfully joined.
MASTER[24826]: Thread 1 successfully joined.
[24826] Thread 4 is shutting down.
[24826] Thread 2 is shutting down.
MASTER[24826]: Thread 2 successfully joined.
[24826] Thread 3 got request: GET /www/bigfile.html HTTP/1.0
[24826] Thread 3 got request: GET /www/bigfile.html HTTP/1.0
[24826] Thread 3 got request: GET /www/bigfile.html HTTP/1.0
[...]
Greetings,
Joachim
PS: Thank you for providing NSPR. It is a lot of fun to write platform
independent programs with it, and I really learn a lot by doing this.
Thank you!