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!
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.