Browse code

- fork_process & fork_tcp_process fixes - reverted to the old fork()-in-parallel behaviour (uncomment FORK_DONT_WAIT for the "serial" fork()).

Andrei Pelinescu-Onciul authored on 02/10/2006 17:29:23
Showing 5 changed files
... ...
@@ -67,7 +67,7 @@ MAIN_NAME=ser
67 67
 VERSION = 0
68 68
 PATCHLEVEL = 10
69 69
 SUBLEVEL =   99
70
-EXTRAVERSION = -dev46-dns_cache
70
+EXTRAVERSION = -dev47-dns_cache
71 71
 
72 72
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
73 73
 			$(SUBLEVEL) )
... ...
@@ -46,15 +46,19 @@ modules:
46 46
                          (failure_route only).
47 47
                        - t_branch_replied() -- returns true if the failure 
48 48
                          route is executed for a branch that did receive at
49
-                         least one reply (failure_route only).. It can be used
49
+                         least one reply in the past (the current reply 
50
+                          is not taken into account). It can be used
50 51
                          together with t_branch_timeout() to distinguish 
51 52
                          between a remote side that doesn't respond (some 
52 53
                          provisional reply received) and one that is completely
53
-                          dead.
54
+                          dead. (failure_route only)
54 55
                        - t_any_timeout() -- returns true if any of the current
55 56
                          transaction branches did timeout.
56 57
                        - t_any_replied() -- returns true if at least one branch
57
-                          of the current transaction received one reply.
58
+                          of the current transaction received one reply in the
59
+                          past. If called from a failure_route or an
60
+                          onreply_route, the "current" reply is not taken into
61
+                          account.
58 62
                        - t_is_canceled() -- returns true if the current 
59 63
                          transaction  has been canceled.
60 64
                        - new t_set_fr(timeout_fr_inv, timeout_fr) -- allows
... ...
@@ -441,7 +441,8 @@ failure_route[0]{
441 441
 	</title>
442 442
 	<para>
443 443
 		Returns true if the failure route is executed for a branch that did
444
-		receive at least one reply. It can be used only from the 
444
+		receive at least one reply in the past (the "current" reply is not 
445
+		taken into account). It can be used only from the 
445 446
 		<emphasis>failure_route</emphasis>.
446 447
 	</para>
447 448
 	<example>
... ...
@@ -491,7 +492,8 @@ failure_route[0]{
491 492
 	</title>
492 493
 	<para>
493 494
 		Returns true if at least one of the current transactions branches
494
-		did receive some reply.
495
+		did receive some reply in the past. If called from a failure or
496
+		onreply route, the "current" reply is not taken into account.
495 497
 	</para>
496 498
 	<example>
497 499
 	    <title><function>t_any_replied</function> usage</title>
... ...
@@ -41,6 +41,12 @@
41 41
 #include "sr_module.h"
42 42
 
43 43
 #include <stdio.h>
44
+
45
+#define FORK_DONT_WAIT  /* child doesn't wait for parent before starting 
46
+						   => faster startup, but the child should not assume
47
+						   the parent fixed the pt[] entry for it */
48
+
49
+
44 50
 #ifdef PROFILING
45 51
 #include <sys/gmon.h>
46 52
 
... ...
@@ -108,6 +114,8 @@ int my_pid()
108 114
 	return pt ? pt[process_no].pid : getpid();
109 115
 }
110 116
 
117
+
118
+
111 119
 /**
112 120
  * Forks a new process.
113 121
  * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be
... ...
@@ -118,77 +126,100 @@ int my_pid()
118 126
  */
119 127
 int fork_process(int child_id, char *desc, int make_sock)
120 128
 {
121
-	int pid,old_process_no;
129
+	int pid, child_process_no;
130
+	int ret;
122 131
 #ifdef USE_TCP
123 132
 	int sockfd[2];
124 133
 #endif
125 134
 
126
-	lock_get(process_lock);	
127
-	if (*process_count>=estimated_proc_no) {
128
-		LOG(L_CRIT, "ERROR: fork_process(): Process limit of %d exceeded."
129
-					" Will simulate fork fail.\n", estimated_proc_no);
130
-		lock_release(process_lock);
131
-		return -1;
132
-	}	
133
-	
135
+	ret=-1;
134 136
 	#ifdef USE_TCP
137
+		sockfd[0]=sockfd[1]=-1;
135 138
 		if(make_sock && !tcp_disable){
136 139
 			 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
137 140
 				LOG(L_ERR, "ERROR: fork_process(): socketpair failed: %s\n",
138
-					strerror(errno));
139
-				return -1;
141
+							strerror(errno));
142
+				goto error;
140 143
 			}
141 144
 		}
142 145
 	#endif
146
+	lock_get(process_lock);
147
+	if (*process_count>=estimated_proc_no) {
148
+		LOG(L_CRIT, "ERROR: fork_process(): Process limit of %d exceeded."
149
+					" Will simulate fork fail.\n", estimated_proc_no);
150
+		lock_release(process_lock);
151
+		goto error;
152
+	}	
143 153
 	
144
-	old_process_no = process_no;
145
-	process_no = *process_count;
154
+	
155
+	child_process_no = *process_count;
146 156
 	pid = fork();
147 157
 	if (pid<0) {
148 158
 		lock_release(process_lock);
149
-		return pid;
150
-	}
151
-	if (pid==0){
159
+		ret=pid;
160
+		goto error;
161
+	}else if (pid==0){
152 162
 		/* child */
163
+		process_no=child_process_no;
153 164
 #ifdef PROFILING
154 165
 		monstartup((u_long) &_start, (u_long) &etext);
155 166
 #endif
167
+#ifdef FORK_DONT_WAIT
168
+		/* record pid twice to avoid the child using it, before
169
+		 * parent gets a chance to set it*/
170
+		pt[process_no].pid=getpid();
171
+#else
156 172
 		/* wait for parent to get out of critical zone.
157 173
 		 * this is actually relevant as the parent updates
158 174
 		 * the pt & process_count. */
159 175
 		lock_get(process_lock);
176
+		lock_release(process_lock);	
177
+#endif
160 178
 		#ifdef USE_TCP
161 179
 			if (make_sock && !tcp_disable){
162 180
 				close(sockfd[0]);
163 181
 				unix_tcp_sock=sockfd[1];
164 182
 			}
165 183
 		#endif		
166
-		lock_release(process_lock);	
167 184
 		if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
168
-			LOG(L_ERR, "ERROR: fork_process(): init_child failed for %s\n",
169
-						pt[process_no].desc);
185
+			LOG(L_ERR, "ERROR: fork_process(): init_child failed for "
186
+					" process %d, pid %d, \"%s\"\n", process_no,
187
+					pt[process_no].pid, pt[process_no].desc);
170 188
 			return -1;
171 189
 		}
172 190
 		return pid;
173 191
 	} else {
174 192
 		/* parent */
175
-		process_no = old_process_no;
193
+		(*process_count)++;
194
+#ifdef FORK_DONT_WAIT
195
+		lock_release(process_lock);
196
+#endif
176 197
 		/* add the process to the list in shm */
177
-		pt[*process_count].pid=pid;
198
+		pt[child_process_no].pid=pid;
178 199
 		if (desc){
179
-			strncpy(pt[*process_count].desc, desc, MAX_PT_DESC);
200
+			strncpy(pt[child_process_no].desc, desc, MAX_PT_DESC);
180 201
 		}
181 202
 		#ifdef USE_TCP
182 203
 			if (make_sock && !tcp_disable){
183 204
 				close(sockfd[1]);
184
-				pt[*process_count].unix_sock=sockfd[0];
185
-				pt[*process_count].idx=-1; /* this is not "tcp" process*/
205
+				pt[child_process_no].unix_sock=sockfd[0];
206
+				pt[child_process_no].idx=-1; /* this is not "tcp" process*/
186 207
 			}
187
-		#endif		
188
-		*process_count = (*process_count) +1;
208
+		#endif
209
+#ifdef FORK_DONT_WAIT
210
+#else
189 211
 		lock_release(process_lock);
190
-		return pid;
212
+#endif
213
+		ret=pid;
214
+		goto end;
191 215
 	}
216
+error:
217
+#ifdef USE_TCP
218
+	if (sockfd[0]!=-1) close(sockfd[0]);
219
+	if (sockfd[1]!=-1) close(sockfd[1]);
220
+#endif
221
+end:
222
+	return ret;
192 223
 }
193 224
 
194 225
 /**
... ...
@@ -199,31 +230,27 @@ int fork_process(int child_id, char *desc, int make_sock)
199 230
  * @returns the pid of the new process
200 231
  */
201 232
 #ifdef USE_TCP
202
-int fork_tcp_process(int child_id,char *desc,int r,int *reader_fd_1)
233
+int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
203 234
 {
204
-	int pid,old_process_no;
235
+	int pid, child_process_no;
205 236
 	int sockfd[2];
206 237
 	int reader_fd[2]; /* for comm. with the tcp children read  */
207
-
208
-
238
+	int ret;
209 239
 	
210
-	lock_get(process_lock);
211
-	/* set the local process_no */
212
-	if (*process_count>=estimated_proc_no) {
213
-		LOG(L_CRIT, "ERROR: fork_tcp_process(): Process limit of %d exceeded."
214
-					" Simulating fork fail\n", estimated_proc_no);
215
-		return -1;
216
-	}	
240
+	/* init */
241
+	sockfd[0]=sockfd[1]=-1;
242
+	reader_fd[0]=reader_fd[1]=-1;
243
+	ret=-1;
217 244
 	
218 245
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
219 246
 		LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
220 247
 					strerror(errno));
221
-		return -1;
248
+		goto error;
222 249
 	}
223 250
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
224 251
 		LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
225 252
 					strerror(errno));
226
-		return -1;
253
+		goto error;
227 254
 	}
228 255
 	if (tcp_fix_child_sockets(reader_fd)<0){
229 256
 		LOG(L_ERR, "ERROR: fork_tcp_process(): failed to set non blocking"
... ...
@@ -231,54 +258,85 @@ int fork_tcp_process(int child_id,char *desc,int r,int *reader_fd_1)
231 258
 		/* continue, it's not critical (it will go slower under
232 259
 		 * very high connection rates) */
233 260
 	}
261
+	lock_get(process_lock);
262
+	/* set the local process_no */
263
+	if (*process_count>=estimated_proc_no) {
264
+		LOG(L_CRIT, "ERROR: fork_tcp_process(): Process limit of %d exceeded."
265
+					" Simulating fork fail\n", estimated_proc_no);
266
+		lock_release(process_lock);
267
+		goto error;
268
+	}
269
+	
234 270
 	
235
-	old_process_no = process_no;
236
-	process_no = *process_count;
271
+	child_process_no = *process_count;
237 272
 	pid = fork();
238 273
 	if (pid<0) {
239 274
 		lock_release(process_lock);
240
-		return pid;
275
+		ret=pid;
276
+		goto end;
241 277
 	}
242 278
 	if (pid==0){
279
+		process_no=child_process_no;
243 280
 #ifdef PROFILING
244 281
 		monstartup((u_long) &_start, (u_long) &etext);
245 282
 #endif
283
+#ifdef FORK_DONT_WAIT
284
+		/* record pid twice to avoid the child using it, before
285
+-		 * parent gets a chance to set it*/
286
+		pt[process_no].pid=getpid();
287
+#else
246 288
 		/* wait for parent to get out of critical zone */
247 289
 		lock_get(process_lock);
248
-			close(sockfd[0]);
249
-			unix_tcp_sock=sockfd[1];
250
-			if (reader_fd_1) *reader_fd_1=reader_fd[1];
251 290
 		lock_release(process_lock);
252
-		if (init_child(child_id) < 0) {
291
+#endif
292
+		close(sockfd[0]);
293
+		unix_tcp_sock=sockfd[1];
294
+		close(reader_fd[0]);
295
+		if (reader_fd_1) *reader_fd_1=reader_fd[1];
296
+		if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
253 297
 			LOG(L_ERR, "ERROR: fork_tcp_process(): init_child failed for "
254
-					"%s\n", pt[process_no].desc);
298
+					"process %d, pid %d, \"%s\"\n", process_no, 
299
+					pt[process_no].pid, pt[process_no].desc);
255 300
 			return -1;
256 301
 		}
257 302
 		return pid;
258 303
 	} else {
259
-		/* parent */		
260
-		process_no = old_process_no;
304
+		/* parent */
305
+		(*process_count)++;
306
+#ifdef FORK_DONT_WAIT
307
+		lock_release(process_lock);
308
+#endif
261 309
 		/* add the process to the list in shm */
262
-		pt[*process_count].pid=pid;
263
-		pt[*process_count].unix_sock=sockfd[0];
264
-		pt[*process_count].idx=r; 	
310
+		pt[child_process_no].pid=pid;
311
+		pt[child_process_no].unix_sock=sockfd[0];
312
+		pt[child_process_no].idx=r;
265 313
 		if (desc){
266
-			snprintf(pt[*process_count].desc, MAX_PT_DESC, "%s child=%d", 
314
+			snprintf(pt[child_process_no].desc, MAX_PT_DESC, "%s child=%d", 
267 315
 						desc, r);
268 316
 		}
317
+#ifdef FORK_DONT_WAIT
318
+#else
319
+		lock_release(process_lock);
320
+#endif
269 321
 		
270 322
 		close(sockfd[1]);
271 323
 		close(reader_fd[1]);
272 324
 		
273 325
 		tcp_children[r].pid=pid;
274
-		tcp_children[r].proc_no=process_no;
326
+		tcp_children[r].proc_no=child_process_no;
275 327
 		tcp_children[r].busy=0;
276 328
 		tcp_children[r].n_reqs=0;
277 329
 		tcp_children[r].unix_sock=reader_fd[0];
278 330
 		
279
-		*process_count = (*process_count) +1;
280
-		lock_release(process_lock);
281
-		return pid;
331
+		ret=pid;
332
+		goto end;
282 333
 	}
334
+error:
335
+	if (sockfd[0]!=-1) close(sockfd[0]);
336
+	if (sockfd[1]!=-1) close(sockfd[1]);
337
+	if (reader_fd[0]!=-1) close(reader_fd[0]);
338
+	if (reader_fd[1]!=-1) close(reader_fd[1]);
339
+end:
340
+	return ret;
283 341
 }
284 342
 #endif
... ...
@@ -1986,7 +1986,7 @@ int tcp_init_children()
1986 1986
 	/* fork children & create the socket pairs*/
1987 1987
 	for(r=0; r<tcp_children_no; r++){
1988 1988
 		child_rank++;
1989
-		pid=fork_tcp_process(child_rank,"tcp receiver",1,&reader_fd_1);
1989
+		pid=fork_tcp_process(child_rank, "tcp receiver", r, &reader_fd_1);
1990 1990
 		if (pid<0){
1991 1991
 			LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
1992 1992
 					strerror(errno));