/[hydra]/hydra/src/select.c
ViewVC logotype

Contents of /hydra/src/select.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations)
Wed Oct 2 19:26:15 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_6
Changes since 1.6: +2 -2 lines
File MIME type: text/plain
Better use of limits. If getrlimit() returns a cur limit less than max limit, we increase the cur limit.

1 /*
2 * Hydra, an http server
3 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4 * Some changes Copyright (C) 1996 Charles F. Randall <crandall@goldsys.com>
5 * Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
6 * Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org>
7 * Portions Copyright (C) 2002 Nikos Mavroyanopoulos <nmav@gnutls.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 /* $Id: select.c,v 1.6 2002/09/28 16:32:37 nmav Exp $*/
26
27 #include "boa.h"
28 #ifdef ENABLE_SMP
29 extern pthread_t father_id;
30 #endif
31
32 static void fdset_update( server_params *);
33
34 /* params->server_s[0] is the plain socket, while the
35 * params->server_s[1] is the ssl one.
36 */
37 void* select_loop(void* _params)
38 {
39 server_params* params = _params;
40
41 #ifdef ENABLE_SMP
42 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);
43 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
44 #endif
45
46 FD_ZERO(&params->block_read_fdset);
47 FD_ZERO(&params->block_write_fdset);
48 /* set server_s and req_timeout */
49 params->req_timeout.tv_sec = (ka_timeout ? ka_timeout : REQUEST_TIMEOUT);
50 params->req_timeout.tv_usec = 0l; /* reset timeout */
51
52 /* preset max_fd */
53 params->max_fd = -1;
54
55 while (1) {
56
57 if (params->sigchld_flag)
58 sigchld_run();
59
60 #ifdef ENABLE_SMP
61 /* Only the main thread handles signals.
62 */
63 if (pthread_equal( params->tid, father_id)) {
64 #endif
65 /* Calculate current time. Moved here, so only one thread
66 * calls this.
67 */
68 time(&current_time);
69
70 if (params->sighup_flag)
71 sighup_run();
72 if (params->sigalrm_flag)
73 sigalrm_run();
74 if (params->sigusr1_flag)
75 sigusr1_run();
76 if (params->sigterm_flag) {
77 if (params->sigterm_flag == 1) {
78 sigterm_stage1_run();
79 }
80 if (params->sigterm_flag == 2 && !params->request_ready && !params->request_block) {
81 sigterm_stage2_run();
82 }
83 }
84 #ifdef ENABLE_SMP
85 }
86 #endif
87
88 /* reset max_fd */
89 params->max_fd = -1;
90
91 if (params->request_block)
92 /* move selected req's from request_block to request_ready */
93 fdset_update( params);
94
95 /* any blocked req's move from request_ready to request_block */
96 if (params->server_s[0].socket != -1) process_requests(params, &params->server_s[0]);
97 #ifdef ENABLE_SSL
98 if (params->server_s[1].socket != -1) process_requests(params, &params->server_s[1]);
99 #endif
100
101 if (!params->sigterm_flag) {
102 if (params->server_s[0].socket != -1) BOA_FD_SET(params->server_s[0].socket, &params->block_read_fdset); /* server always set */
103 #ifdef ENABLE_SSL
104 if (params->server_s[1].socket != -1) BOA_FD_SET(params->server_s[1].socket, &params->block_read_fdset); /* server always set */
105 #endif
106 }
107
108 params->req_timeout.tv_sec = ((params->request_ready) ? 0 :
109 (ka_timeout ? ka_timeout : REQUEST_TIMEOUT));
110 params->req_timeout.tv_usec = 0l; /* reset timeout */
111
112 if (select(params->max_fd + 1, &params->block_read_fdset,
113 &params->block_write_fdset, NULL,
114 ((params->request_ready || params->request_block) ? &params->req_timeout : NULL)) == -1) {
115 /* what is the appropriate thing to do here on EBADF */
116 if (errno == EINTR)
117 continue; /* while(1) */
118 else if (errno != EBADF) {
119 DIE("select");
120 }
121 }
122
123 if (params->server_s[0].socket != -1 && FD_ISSET(params->server_s[0].socket, &params->block_read_fdset))
124 params->server_s[0].pending_requests = 1;
125 #ifdef ENABLE_SSL
126 if (params->server_s[1].socket != -1 && FD_ISSET(params->server_s[1].socket, &params->block_read_fdset))
127 params->server_s[1].pending_requests = 1;
128 #endif
129 }
130
131 return NULL;
132 }
133
134 /*
135 * Name: fdset_update
136 *
137 * Description: iterate through the blocked requests, checking whether
138 * that file descriptor has been set by select. Update the fd_set to
139 * reflect current status.
140 *
141 * Here, we need to do some things:
142 * - keepalive timeouts simply close
143 * (this is special:: a keepalive timeout is a timeout where
144 keepalive is active but nothing has been read yet)
145 * - regular timeouts close + error
146 * - stuff in buffer and fd ready? write it out
147 * - fd ready for other actions? do them
148 */
149
150 static void fdset_update( server_params* params)
151 {
152 request *current, *next;
153
154 for(current = params->request_block;current;current = next) {
155 time_t time_since = current_time - current->time_last;
156 next = current->next;
157
158 /* hmm, what if we are in "the middle" of a request and not
159 * just waiting for a new one... perhaps check to see if anything
160 * has been read via header position, etc... */
161 if (current->kacount < ka_max && /* we *are* in a keepalive */
162 (time_since >= ka_timeout) && /* ka timeout */
163 !current->logline) /* haven't read anything yet */
164 current->status = DEAD; /* connection keepalive timed out */
165 else if (time_since > REQUEST_TIMEOUT) {
166 log_error_doc(current);
167 fputs("connection timed out\n", stderr);
168 current->status = DEAD;
169 }
170 if (current->buffer_end && current->status < DEAD) {
171 if (FD_ISSET(current->fd, &params->block_write_fdset))
172 ready_request( params, current);
173 else {
174 BOA_FD_SET(current->fd, &params->block_write_fdset);
175 }
176 } else {
177 switch (current->status) {
178 case WRITE:
179 case PIPE_WRITE:
180 if (FD_ISSET(current->fd, &params->block_write_fdset))
181 ready_request( params, current);
182 else {
183 BOA_FD_SET(current->fd, &params->block_write_fdset);
184 }
185 break;
186 case BODY_WRITE:
187 if (FD_ISSET(current->post_data_fd, &params->block_write_fdset))
188 ready_request( params, current);
189 else {
190 BOA_FD_SET(current->post_data_fd, &params->block_write_fdset);
191 }
192 break;
193 case PIPE_READ:
194 if (FD_ISSET(current->data_fd, &params->block_read_fdset))
195 ready_request( params, current);
196 else {
197 BOA_FD_SET(current->data_fd, &params->block_read_fdset);
198 }
199 break;
200 case DONE:
201 if (FD_ISSET(current->fd, &params->block_write_fdset))
202 ready_request( params, current);
203 else {
204 BOA_FD_SET(current->fd, &params->block_write_fdset);
205 }
206 break;
207 case DEAD:
208 ready_request( params, current);
209 break;
210 default:
211 if (FD_ISSET(current->fd, &params->block_read_fdset))
212 ready_request( params, current);
213 else {
214 BOA_FD_SET(current->fd, &params->block_read_fdset);
215 }
216 break;
217 }
218 }
219 current = next;
220 }
221 }
222

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26