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

Contents of /hydra/src/select.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Wed Oct 9 08:49:46 2002 UTC (21 years, 5 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_7
Changes since 1.7: +5 -8 lines
File MIME type: text/plain
Improved the thread killing mechanism, to avoid unexpected errors. Now childen threads are killed with a HUP signal instead of pthread_cancel().

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.7 2002/10/02 19:26:15 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 FD_ZERO(&params->block_read_fdset);
42 FD_ZERO(&params->block_write_fdset);
43 /* set server_s and req_timeout */
44 params->req_timeout.tv_sec = (ka_timeout ? ka_timeout : REQUEST_TIMEOUT);
45 params->req_timeout.tv_usec = 0l; /* reset timeout */
46
47 /* preset max_fd */
48 params->max_fd = -1;
49
50 while (1) {
51
52 if (params->sigchld_flag)
53 sigchld_run();
54
55 #ifdef ENABLE_SMP
56 /* Only the main thread handles signals.
57 */
58 if (pthread_equal( params->tid, father_id)) {
59 #endif
60 /* Calculate current time. Moved here, so only one thread
61 * calls this.
62 */
63 time(&current_time);
64
65 if (params->sigalrm_flag)
66 sigalrm_run();
67 if (params->sigusr1_flag)
68 sigusr1_run();
69 if (params->sigterm_flag) {
70 if (params->sigterm_flag == 1) {
71 sigterm_stage1_run();
72 }
73 if (params->sigterm_flag == 2 && !params->request_ready && !params->request_block) {
74 sigterm_stage2_run();
75 }
76 }
77 #ifdef ENABLE_SMP
78 }
79 #endif
80 /* the whole family calls this
81 */
82 if (params->sighup_flag)
83 sighup_run();
84
85 /* reset max_fd */
86 params->max_fd = -1;
87
88 if (params->request_block)
89 /* move selected req's from request_block to request_ready */
90 fdset_update( params);
91
92 /* any blocked req's move from request_ready to request_block */
93 if (params->server_s[0].socket != -1) process_requests(params, &params->server_s[0]);
94 #ifdef ENABLE_SSL
95 if (params->server_s[1].socket != -1) process_requests(params, &params->server_s[1]);
96 #endif
97
98 if (!params->sigterm_flag) {
99 if (params->server_s[0].socket != -1) BOA_FD_SET(params->server_s[0].socket, &params->block_read_fdset); /* server always set */
100 #ifdef ENABLE_SSL
101 if (params->server_s[1].socket != -1) BOA_FD_SET(params->server_s[1].socket, &params->block_read_fdset); /* server always set */
102 #endif
103 }
104
105 params->req_timeout.tv_sec = ((params->request_ready) ? 0 :
106 (ka_timeout ? ka_timeout : REQUEST_TIMEOUT));
107 params->req_timeout.tv_usec = 0l; /* reset timeout */
108
109 if (select(params->max_fd + 1, &params->block_read_fdset,
110 &params->block_write_fdset, NULL,
111 ((params->request_ready || params->request_block) ? &params->req_timeout : NULL)) == -1) {
112 /* what is the appropriate thing to do here on EBADF */
113 if (errno == EINTR)
114 continue; /* while(1) */
115 else if (errno != EBADF) {
116 DIE("select");
117 }
118 }
119
120 if (params->server_s[0].socket != -1 && FD_ISSET(params->server_s[0].socket, &params->block_read_fdset))
121 params->server_s[0].pending_requests = 1;
122 #ifdef ENABLE_SSL
123 if (params->server_s[1].socket != -1 && FD_ISSET(params->server_s[1].socket, &params->block_read_fdset))
124 params->server_s[1].pending_requests = 1;
125 #endif
126 }
127
128 return NULL;
129 }
130
131 /*
132 * Name: fdset_update
133 *
134 * Description: iterate through the blocked requests, checking whether
135 * that file descriptor has been set by select. Update the fd_set to
136 * reflect current status.
137 *
138 * Here, we need to do some things:
139 * - keepalive timeouts simply close
140 * (this is special:: a keepalive timeout is a timeout where
141 keepalive is active but nothing has been read yet)
142 * - regular timeouts close + error
143 * - stuff in buffer and fd ready? write it out
144 * - fd ready for other actions? do them
145 */
146
147 static void fdset_update( server_params* params)
148 {
149 request *current, *next;
150
151 for(current = params->request_block;current;current = next) {
152 time_t time_since = current_time - current->time_last;
153 next = current->next;
154
155 /* hmm, what if we are in "the middle" of a request and not
156 * just waiting for a new one... perhaps check to see if anything
157 * has been read via header position, etc... */
158 if (current->kacount < ka_max && /* we *are* in a keepalive */
159 (time_since >= ka_timeout) && /* ka timeout */
160 !current->logline) /* haven't read anything yet */
161 current->status = DEAD; /* connection keepalive timed out */
162 else if (time_since > REQUEST_TIMEOUT) {
163 log_error_doc(current);
164 fputs("connection timed out\n", stderr);
165 current->status = DEAD;
166 }
167 if (current->buffer_end && current->status < DEAD) {
168 if (FD_ISSET(current->fd, &params->block_write_fdset))
169 ready_request( params, current);
170 else {
171 BOA_FD_SET(current->fd, &params->block_write_fdset);
172 }
173 } else {
174 switch (current->status) {
175 case WRITE:
176 case PIPE_WRITE:
177 if (FD_ISSET(current->fd, &params->block_write_fdset))
178 ready_request( params, current);
179 else {
180 BOA_FD_SET(current->fd, &params->block_write_fdset);
181 }
182 break;
183 case BODY_WRITE:
184 if (FD_ISSET(current->post_data_fd, &params->block_write_fdset))
185 ready_request( params, current);
186 else {
187 BOA_FD_SET(current->post_data_fd, &params->block_write_fdset);
188 }
189 break;
190 case PIPE_READ:
191 if (FD_ISSET(current->data_fd, &params->block_read_fdset))
192 ready_request( params, current);
193 else {
194 BOA_FD_SET(current->data_fd, &params->block_read_fdset);
195 }
196 break;
197 case DONE:
198 if (FD_ISSET(current->fd, &params->block_write_fdset))
199 ready_request( params, current);
200 else {
201 BOA_FD_SET(current->fd, &params->block_write_fdset);
202 }
203 break;
204 case DEAD:
205 ready_request( params, current);
206 break;
207 default:
208 if (FD_ISSET(current->fd, &params->block_read_fdset))
209 ready_request( params, current);
210 else {
211 BOA_FD_SET(current->fd, &params->block_read_fdset);
212 }
213 break;
214 }
215 }
216 current = next;
217 }
218 }
219

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26