manoj 99/05/27 17:19:34
Modified: pthreads/src/main http_accept.c Log: Squash a potential thread-safeness bug. Every thread could touch the lr and head_listener pointers at the same time when accepts weren't serialized. So, put back the special condition for one listen socket where we don't bother with lr and head_listener at all. Revision Changes Path 1.17 +40 -31 apache-apr/pthreads/src/main/http_accept.c Index: http_accept.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/http_accept.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -u -r1.16 -r1.17 --- http_accept.c 1999/05/24 06:18:47 1.16 +++ http_accept.c 1999/05/28 00:19:33 1.17 @@ -400,38 +400,48 @@ if (srv == 0) { /* Is srv == 0 a valid return? */ continue; - } + } - /* find a listener */ - /* Loop or NULL terminated list? That is the question. Be consistent across - all the accept techniques */ - lr = head_listener; - do { - /* XXX: should we check for PR_POLL_ERR ?? */ - if (listenfds[lr->index].revents & POLLIN) { - /* advance to the next listener for next loop */ - head_listener = lr->next; - /* hack to handle listenfds being NULL terminated list - * rather than a loop - */ - if (!head_listener) { - head_listener = ap_listeners; + /* This conditional is used because the single listen case is the + * only one where the accept might not be serialized. In that + * case, multiple threads mucking around with the head_listener + * pointer will be harmful */ + if (num_listenfds == 1) { + /* only one socket, just pretend we did the other stuff */ + sd = ap_listeners->fd; + } + else { + /* find a listener */ + /* Loop or NULL terminated list? That is the question. Be + * consistent across all the accept techniques */ + lr = head_listener; + do { + /* XXX: should we check for PR_POLL_ERR ?? */ + if (listenfds[lr->index].revents & POLLIN) { + /* advance to the next listener for next loop */ + head_listener = lr->next; + /* hack to handle listenfds being NULL terminated list + * rather than a loop + */ + if (head_listener == NULL) { + head_listener = ap_listeners; + } + goto got_lr; } - goto got_lr; - } - lr = lr->next; - if (lr == NULL) { - lr = ap_listeners; - } - } while (lr != head_listener); - - /* if we don't find anything then just start again */ - fprintf(stderr,"poll returned but we got nothing!\n"); - head_listener = ap_listeners; - continue; - - got_lr: - sd = lr->fd; + lr = lr->next; + if (lr == NULL) { + lr = ap_listeners; + } + } while (lr != head_listener); + + /* if we don't find anything then just start again */ + fprintf(stderr,"poll returned but we got nothing!\n"); + head_listener = ap_listeners; + continue; + + got_lr: + sd = lr->fd; + } csd = accept(sd, sa_client, &len); requests_this_child--; @@ -439,7 +449,6 @@ break; /* We have a socket ready for reading */ /* XXX: we need to deal with error conditions here */ } - SAFE_ACCEPT(accept_mutex_off(0)); SAFE_ACCEPT(intra_mutex_off(0));