Browse code

- applied patch from Dragos Vingarzan <vingarzan@fokus.fraunhofer.de> which moves all the forking part into 2 functions in pt.c (fork_process and fork_tcp_process). - added PROC_NOCHLDINIT rank value for Dragos's fork_process (if this value is used as child_id/rank_value the mod_child functions will not be called) - added register_procs(processes_no), used from mod_init when a module knows that it will fork some children (replaces the old process_count++ / the patch's estimated_process_count++) - added get_max_procs(): returns the maximum (estimated) number of processes

Andrei Pelinescu-Onciul authored on 19/09/2006 16:13:27
Showing 11 changed files
... ...
@@ -66,7 +66,7 @@ MAIN_NAME=ser
66 66
 VERSION = 0
67 67
 PATCHLEVEL = 10
68 68
 SUBLEVEL =   99
69
-EXTRAVERSION = -dev44-dns_cache
69
+EXTRAVERSION = -dev45-dns_cache
70 70
 
71 71
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
72 72
 			$(SUBLEVEL) )
... ...
@@ -216,7 +216,7 @@ static void core_ps(rpc_t* rpc, void* c)
216 216
 {
217 217
 	int p;
218 218
 
219
-	for (p=0; p<process_count;p++) {
219
+	for (p=0; p<*process_count;p++) {
220 220
 		rpc->add(c, "d", pt[p].pid);
221 221
 		rpc->add(c, "s", pt[p].desc);
222 222
 	}
... ...
@@ -13,7 +13,7 @@ Overview
13 13
   and negative) and look first in its internal cache.
14 14
  When its internal dns cache is enabled, ser can also use dns failover: if
15 15
   one destination resolves to multiple addresses ser can try all of them until
16
-  it finds one to which it can succesfully send the packet or it exhausts all 
16
+  it finds one to which it can successfully send the packet or it exhausts all 
17 17
   of them. ser (tm to be more precise) uses the dns failover also when the
18 18
   destination host doesn't send any reply to a forwarded invite within the
19 19
   sip timeout interval (whose value can be configured using the tm fr_timer
... ...
@@ -27,19 +27,19 @@ DNS Cache and Failover Drawbacks
27 27
   1. only the locally configured dns server (usually in /etc/resolv.conf) is
28 28
   used for the requests (/etc/hosts and the local Network Information Service
29 29
   are ignored). 
30
-     Workarround: disable the dns cache (use_dns_cache=off or
30
+     Workaround: disable the dns cache (use_dns_cache=off or
31 31
   compile without -DUSE_DNS_CACHE).
32 32
 
33 33
   2. the dns cache uses extra memory
34
-      Workarround: disable the dns cache.
34
+      Workaround: disable the dns cache.
35 35
 
36 36
   3. the dns failover introduces a very small performance penalty 
37
-     Workarround: disable the dns failover (use_dns_failover=off).
37
+     Workaround: disable the dns failover (use_dns_failover=off).
38 38
 
39 39
   4. the dns failover increases the memory usage (the internal structures
40 40
   used to represent the transaction are bigger when the dns failover support is
41 41
   compiled).
42
-     Workarround: compile without dns failover support (-DUSE_DNS_FAILOVER).
42
+     Workaround: compile without dns failover support (-DUSE_DNS_FAILOVER).
43 43
   Turning it off from the config file is not enough in this case (the extra
44 44
    memory will still be used).
45 45
 
... ...
@@ -94,7 +94,7 @@ DNS Resolver Options
94 94
  server configured in /etc/resolv.conf, set the dns resolver options in ser's
95 95
  config as in the above example and enable the dns cache (in ser).
96 96
  Pay particular attention to dns_servers_no and dns_use_search_list. It's a
97
- good ideea to make sure you don't need / use the search list or more then one
97
+ good idea to make sure you don't need / use the search list or more then one
98 98
  dns server (to avoid unnecessary extra lookups).
99 99
 
100 100
 
... ...
@@ -22,7 +22,7 @@ Drawbacks
22 22
  Using the destination blacklist will cause some performance degradation,
23 23
  especially on multi cpu machines. If you don't need it you can easily
24 24
   disable it, either in ser's config or at compile time. Disabling it at
25
-  compile time is sligthly better (but not in a "measurable" way) then
25
+  compile time is slightly better (but not in a "measurable" way) then
26 26
    disabling it at runtime, from the config file.
27 27
  Whether the destination blacklist is better to be on or off depends a lot
28 28
   on the setup. In general is better to turn it on when:
... ...
@@ -47,7 +47,7 @@ Config Variables
47 47
   Note: using the blacklist incurs a small performance penalty.
48 48
 
49 49
  dst_blacklist_mem = size in Kb (default 250 Kb) - maximum
50
-  shared memory ammount used for keeping the blacklisted destinations.
50
+  shared memory amount used for keeping the blacklisted destinations.
51 51
 
52 52
  dst_blacklist_expire = time in s (default 60 s) - how much time a 
53 53
   blacklisted destination will be kept in the blacklist (w/o any update).
... ...
@@ -66,4 +66,4 @@ Compile Options
66 66
    form DEFS list. To add a compile options add it to the make command line,
67 67
      e.g.: make proper; make all extra_defs=-DUSE_DNS_FAILOVER
68 68
    or for a permanent solution, edit Makefile.defs and add it to DEFS 
69
-   (don't foget to prefix it with -D).
69
+   (don't forget to prefix it with -D).
... ...
@@ -246,8 +246,14 @@ int tcp_disable = 0; /* 1 if tcp is disabled */
246 246
 #ifdef USE_TLS
247 247
 int tls_disable = 0; /* 1 if tls is disabled */
248 248
 #endif
249
+
249 250
 struct process_table *pt=0;		/*array with children pids, 0= main proc,
250 251
 									alloc'ed in shared mem if possible*/
252
+int *process_count = 0;			/* Total number of SER processes currently 
253
+								   running */
254
+gen_lock_t* process_lock;		/* lock on the process table */
255
+int process_no = 0;				/* index of process in the pt */
256
+
251 257
 int sig_flag = 0;              /* last signal received */
252 258
 int debug = L_DEFAULT; /* print only msg. < L_WARN */
253 259
 int dont_fork = 0;
... ...
@@ -349,20 +355,9 @@ unsigned short tls_port_no=0; /* default port */
349 349
 
350 350
 struct host_alias* aliases=0; /* name aliases list */
351 351
 
352
-/* ipc related globals */
353
-int process_no = 0;
354
-
355 352
 /* Parameter to child_init */
356 353
 int child_rank = 0;
357 354
 
358
-/* Last filled entry in process table before calling
359
- * child_init of loaded modules
360
- */
361
-int last_process = 0;
362
-
363
-/* Total number of SER processes with given configuration */
364
-int process_count = 0;
365
-
366 355
 /* process_bm_t process_bit = 0; */
367 356
 #ifdef ROUTE_SRV
368 357
 #endif
... ...
@@ -456,9 +451,17 @@ static void kill_all_children(int signum)
456 456
 	int r;
457 457
 
458 458
 	if (own_pgid) kill(0, signum);
459
-	else if (pt)
460
-		for (r=1; r<process_count; r++)
461
-			if (pt[r].pid) kill(pt[r].pid, signum);
459
+	else if (pt){
460
+		lock_get(process_lock);
461
+		for (r=1; r<*process_count; r++){
462
+			if (pt[r].pid) {
463
+				kill(pt[r].pid, signum);
464
+			}
465
+			else LOG(L_CRIT, "BUG: killing: %s > %d no pid!!!\n",
466
+							pt[r].desc, pt[r].pid);
467
+		}
468
+		lock_release(process_lock);
469
+	}
462 470
 }
463 471
 
464 472
 
... ...
@@ -803,9 +806,6 @@ int main_loop()
803 803
 	int  i;
804 804
 	pid_t pid;
805 805
 	struct socket_info* si;
806
-#ifdef USE_TCP
807
-	int sockfd[2];
808
-#endif
809 806
 #ifdef EXTRA_DEBUG
810 807
 	int r;
811 808
 #endif
... ...
@@ -838,53 +838,34 @@ int main_loop()
838 838
 
839 839
 #ifdef USE_SLOW_TIMER
840 840
 		/* we need another process to act as the "slow" timer*/
841
-				process_no++;
842
-				if ((pid=fork())<0){
841
+				pid = fork_process(PROC_TIMER, "slow timer", 0);
842
+				if (pid<0){
843 843
 					LOG(L_CRIT,  "ERROR: main_loop: Cannot fork\n");
844 844
 					goto error;
845 845
 				}
846 846
 				if (pid==0){
847 847
 					/* child */
848
-					pt[process_no].pid=getpid();
849 848
 					/* timer!*/
850 849
 					/* process_bit = 0; */
851
-					if (init_child(PROC_TIMER) < 0) {
852
-						LOG(L_ERR, "slow timer: init_child failed\n");
853
-						goto error;
854
-					}
855
-
856 850
 					if (arm_slow_timer()<0) goto error;
857 851
 					slow_timer_main();
858 852
 				}else{
859
-					pt[process_no].pid=pid; /*should be shared mem anyway*/
860
-					strncpy(pt[process_no].desc, "slow timer", MAX_PT_DESC );
861 853
 					slow_timer_pid=pid;
862
-
863 854
 				}
864 855
 #endif
865 856
 				/* we need another process to act as the "main" timer*/
866
-				process_no++;
867
-				if ((pid=fork())<0){
857
+				pid = fork_process(PROC_TIMER, "timer", 0);
858
+				if (pid<0){
868 859
 					LOG(L_CRIT,  "ERROR: main_loop: Cannot fork\n");
869 860
 					goto error;
870 861
 				}
871 862
 				if (pid==0){
872 863
 					/* child */
873
-					/* record pid twice to avoid the child using it, before
874
-					 * parent gets a chance to set it*/
875
-					pt[process_no].pid=getpid();
876 864
 					/* timer!*/
877 865
 					/* process_bit = 0; */
878
-					if (init_child(PROC_TIMER) < 0) {
879
-						LOG(L_ERR, "timer: init_child failed\n");
880
-						goto error;
881
-					}
882
-
883 866
 					if (arm_timer()<0) goto error;
884 867
 					timer_main();
885 868
 				}else{
886
-						pt[process_no].pid=pid; /*should be shared mem anyway*/
887
-						strncpy(pt[process_no].desc, "timer", MAX_PT_DESC );
888 869
 				}
889 870
 
890 871
 		/* main process, receive loop */
... ...
@@ -910,9 +891,6 @@ int main_loop()
910 910
 
911 911
 		return udp_rcv_loop();
912 912
 	}else{
913
-		/* process_no now initialized to zero -- increase from now on
914
-		   as new processes are forked (while skipping 0 reserved for main )
915
-		*/
916 913
 
917 914
 		for(si=udp_listen;si;si=si->next){
918 915
 			/* create the listening socket (for each address)*/
... ...
@@ -967,53 +945,22 @@ int main_loop()
967 967
 		/* udp processes */
968 968
 		for(si=udp_listen; si; si=si->next){
969 969
 			for(i=0;i<children_no;i++){
970
-				process_no++;
971 970
 				child_rank++;
972
-#ifdef USE_TCP
973
-				if(!tcp_disable){
974
-		 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
975
-						LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n",
976
-							strerror(errno));
977
-						goto error;
978
-					}
979
-				}
980
-#endif
981
-				if ((pid=fork())<0){
971
+				pid = fork_process(child_rank, "udp", 1);
972
+				if (pid<0){
982 973
 					LOG(L_CRIT,  "main_loop: Cannot fork\n");
983 974
 					goto error;
984 975
 				}else if (pid==0){
985
-					     /* child */
986
-#ifdef USE_TCP
987
-					if (!tcp_disable){
988
-						close(sockfd[0]);
989
-						unix_tcp_sock=sockfd[1];
990
-					}
991
-#endif
992
-					/* record pid twice to avoid the child using it, before
993
-					 * parent gets a chance to set it*/
994
-					pt[process_no].pid=getpid();
976
+					/* child */
995 977
 					bind_address=si; /* shortcut */
996
-					if (init_child(child_rank) < 0) {
997
-						LOG(L_ERR, "init_child failed\n");
998
-						goto error;
999
-					}
1000 978
 #ifdef STATS
1001 979
 					setstats( i+r*children_no );
1002 980
 #endif
1003 981
 					return udp_rcv_loop();
1004 982
 				}else{
1005
-						pt[process_no].pid=pid; /*should be in shared mem.*/
1006 983
 						snprintf(pt[process_no].desc, MAX_PT_DESC,
1007 984
 							"receiver child=%d sock= %s:%s", i,
1008 985
 							si->name.s, si->port_no_str.s );
1009
-#ifdef USE_TCP
1010
-						if (!tcp_disable){
1011
-							close(sockfd[1]);
1012
-							pt[process_no].unix_sock=sockfd[0];
1013
-							pt[process_no].idx=-1; /* this is not a "tcp"
1014
-													  process*/
1015
-						}
1016
-#endif
1017 986
 				}
1018 987
 			}
1019 988
 			/*parent*/
... ...
@@ -1027,94 +974,32 @@ int main_loop()
1027 1027
 
1028 1028
 	{
1029 1029
 #ifdef USE_SLOW_TIMER
1030
-#ifdef USE_TCP
1031
-		if (!tcp_disable){
1032
- 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
1033
-				LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n",
1034
-					strerror(errno));
1035
-				goto error;
1036
-			}
1037
-		}
1038
-#endif
1039 1030
 		/* fork again for the "slow" timer process*/
1040
-		process_no++;
1041
-		if ((pid=fork())<0){
1031
+		pid = fork_process(PROC_TIMER, "slow timer", 1);
1032
+		if (pid<0){
1042 1033
 			LOG(L_CRIT, "main_loop: cannot fork \"slow\" timer process\n");
1043 1034
 			goto error;
1044 1035
 		}else if (pid==0){
1045 1036
 			/* child */
1046 1037
 			/* is_main=0; */
1047
-#ifdef USE_TCP
1048
-			if (!tcp_disable){
1049
-				close(sockfd[0]);
1050
-				unix_tcp_sock=sockfd[1];
1051
-			}
1052
-#endif
1053
-			/* record pid twice to avoid the child using it, before
1054
-			 * parent gets a chance to set it*/
1055
-			pt[process_no].pid=getpid();
1056
-			if (init_child(PROC_TIMER) < 0) {
1057
-				LOG(L_ERR, "slow timer: init_child failed\n");
1058
-				goto error;
1059
-			}
1060 1038
 			if (arm_slow_timer()<0) goto error;
1061 1039
 			slow_timer_main();
1062 1040
 		}else{
1063
-			pt[process_no].pid=pid;
1064
-			strncpy(pt[process_no].desc, "slow timer", MAX_PT_DESC );
1065 1041
 			slow_timer_pid=pid;
1066
-#ifdef USE_TCP
1067
-			if(!tcp_disable){
1068
-						close(sockfd[1]);
1069
-						pt[process_no].unix_sock=sockfd[0];
1070
-						pt[process_no].idx=-1; /* this is not a "tcp" process*/
1071
-			}
1072
-#endif
1073 1042
 		}
1074 1043
 #endif /* USE_SLOW_TIMER */
1075 1044
 
1076 1045
 		/* fork again for the "main" timer process*/
1077
-#ifdef USE_TCP
1078
-		if (!tcp_disable){
1079
- 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
1080
-				LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n",
1081
-					strerror(errno));
1082
-				goto error;
1083
-			}
1084
-		}
1085
-#endif
1086
-		process_no++;
1087
-		if ((pid=fork())<0){
1046
+		pid = fork_process(PROC_TIMER, "timer", 1);
1047
+		if (pid<0){
1088 1048
 			LOG(L_CRIT, "main_loop: cannot fork timer process\n");
1089 1049
 			goto error;
1090 1050
 		}else if (pid==0){
1091 1051
 			/* child */
1092 1052
 			/* is_main=0; */
1093
-#ifdef USE_TCP
1094
-			if (!tcp_disable){
1095
-				close(sockfd[0]);
1096
-				unix_tcp_sock=sockfd[1];
1097
-			}
1098
-#endif
1099
-			/* record pid twice to avoid the child using it, before
1100
-			 * parent gets a chance to set it*/
1101
-			pt[process_no].pid=getpid();
1102
-			if (init_child(PROC_TIMER) < 0) {
1103
-				LOG(L_ERR, "timer: init_child failed\n");
1104
-				goto error;
1105
-			}
1106 1053
 			if (arm_timer()<0) goto error;
1107 1054
 			timer_main();
1108 1055
 		}else{
1109
-			pt[process_no].pid=pid;
1110
-			strncpy(pt[process_no].desc, "timer", MAX_PT_DESC );
1111
-#ifdef USE_TCP
1112
-			if(!tcp_disable){
1113
-						close(sockfd[1]);
1114
-						pt[process_no].unix_sock=sockfd[0];
1115
-						pt[process_no].idx=-1; /* this is not a "tcp" process*/
1116
-			}
1117
-#endif
1118 1056
 		}
1119 1057
 	}
1120 1058
 #ifdef USE_TCP
... ...
@@ -1122,33 +1007,20 @@ int main_loop()
1122 1122
 				/* start tcp  & tls receivers */
1123 1123
 			if (tcp_init_children()<0) goto error;
1124 1124
 				/* start tcp+tls master proc */
1125
-			process_no++;
1126
-			if ((pid=fork())<0){
1125
+			pid = fork_process(PROC_TCP_MAIN, "tcp main process", 0);
1126
+			if (pid<0){
1127 1127
 				LOG(L_CRIT, "main_loop: cannot fork tcp main process: %s\n",
1128 1128
 							strerror(errno));
1129 1129
 				goto error;
1130 1130
 			}else if (pid==0){
1131 1131
 				/* child */
1132
-				/* is_main=0; */
1133
-				/* record pid twice to avoid the child using it, before
1134
-				 * parent gets a chance to set it*/
1135
-				pt[process_no].pid=getpid();
1136
-				if (init_child(PROC_TCP_MAIN) < 0) {
1137
-					LOG(L_ERR, "tcp_main: error in init_child\n");
1138
-					goto error;
1139
-				}
1140 1132
 				tcp_main_loop();
1141 1133
 			}else{
1142
-				pt[process_no].pid=pid;
1143
-				strncpy(pt[process_no].desc, "tcp main process", MAX_PT_DESC );
1144
-				pt[process_no].unix_sock=-1;
1145
-				pt[process_no].idx=-1; /* this is not a "tcp" process*/
1146 1134
 				unix_tcp_sock=-1;
1147 1135
 			}
1148 1136
 		}
1149 1137
 #endif
1150 1138
 	/* main */
1151
-	pt[0].pid=getpid();
1152 1139
 	strncpy(pt[0].desc, "attendant", MAX_PT_DESC );
1153 1140
 #ifdef USE_TCP
1154 1141
 	if(!tcp_disable){
... ...
@@ -1159,11 +1031,6 @@ int main_loop()
1159 1159
 #endif
1160 1160
 	/*DEBUG- remove it*/
1161 1161
 
1162
-	/* Modules need to know the last value of process_no to fill in
1163
-	 * process table properly
1164
-	 */
1165
-	last_process = process_no;
1166
-	process_no=0;
1167 1162
 	/* process_bit = 0; */
1168 1163
 	is_main=1;
1169 1164
 
... ...
@@ -1174,7 +1041,7 @@ int main_loop()
1174 1174
 
1175 1175
 	/*DEBUG- remove it*/
1176 1176
 #ifdef EXTRA_DEBUG
1177
-	for (r=0; r<process_count; r++){
1177
+	for (r=0; r<*process_count; r++){
1178 1178
 		fprintf(stderr, "% 3d   % 5d - %s\n", r, pt[r].pid, pt[r].desc);
1179 1179
 	}
1180 1180
 #endif
... ...
@@ -1326,15 +1193,15 @@ int main(int argc, char** argv)
1326 1326
 					break;
1327 1327
 			case '?':
1328 1328
 					if (isprint(optopt))
1329
-						fprintf(stderr, "Unknown option `-%c�. Use -h for help.\n", optopt);
1329
+						fprintf(stderr, "Unknown option `-%c. Use -h for help.\n", optopt);
1330 1330
 					else
1331 1331
 						fprintf(stderr,
1332
-								"Unknown option character `\\x%x�. Use -h for help.\n",
1332
+								"Unknown option character `\\x%x. Use -h for help.\n",
1333 1333
 								optopt);
1334 1334
 					goto error;
1335 1335
 			case ':':
1336 1336
 					fprintf(stderr,
1337
-								"Option `-%c� requires an argument. Use -h for help.\n",
1337
+								"Option `-%c requires an argument. Use -h for help.\n",
1338 1338
 								optopt);
1339 1339
 					goto error;
1340 1340
 			default:
... ...
@@ -1645,32 +1512,22 @@ try_again:
1645 1645
 			goto error;
1646 1646
 		}
1647 1647
 	}
1648
-	     /* Calculate initial process count, mod_init functions called
1649
-	      * below can add to it
1650
-	      */
1651
-	process_count = calc_proc_no();
1648
+	
1652 1649
 	if (init_modules() != 0) {
1653 1650
 		fprintf(stderr, "ERROR: error while initializing modules\n");
1654 1651
 		goto error;
1655 1652
 	}
1656
-
1657
-	     /* The total number of processes is know now, note that no
1658
-	      * function being called before this point may rely on the
1659
-	      * number of processes !
1660
-	      */
1661
-	DBG("Expect %d SER processes in your process list\n", process_count);
1662
-
1663
-	/*alloc pids*/
1664
-#ifdef SHM_MEM
1665
-	pt=shm_malloc(sizeof(struct process_table)*process_count);
1666
-#else
1667
-	pt=pkg_malloc(sizeof(struct process_table)*process_count);
1668
-#endif
1669
-	if (pt==0){
1670
-		fprintf(stderr, "ERROR: out  of memory\n");
1653
+	/* initialize process_table, add core process no. (calc_proc_no()) to the 
1654
+	 * processes registered from the modules*/
1655
+	if (init_pt(calc_proc_no())==-1)
1671 1656
 		goto error;
1672
-	}
1673
-	memset(pt, 0, sizeof(struct process_table)*process_count);
1657
+	
1658
+	/* The total number of processes is now known, note that no
1659
+	 * function being called before this point may rely on the
1660
+	 * number of processes !
1661
+	 */
1662
+	DBG("Expect (at least) %d SER processes in your process list\n",
1663
+			get_max_procs());
1674 1664
 
1675 1665
 	/* fix routing lists */
1676 1666
 	if ( (r=fix_rls())!=0){
... ...
@@ -58,7 +58,7 @@ int init_tm_stats(void)
58 58
 	     /* Delay initialization of tm_stats structures to
59 59
 	      * init_tm_stats_child which gets called from child_init,
60 60
 	      * in mod_init function other modules can increase the value of
61
-	      * process_count and thus we do not know about processes created
61
+	      * estimated_process_count and thus we do not know about processes created
62 62
 	      * from modules which get loaded after tm and thus their mod_init
63 63
 	      * functions will be called after tm mod_init function finishes
64 64
 	      */
... ...
@@ -70,10 +70,10 @@ int init_tm_stats_child(void)
70 70
 {
71 71
 	int size;
72 72
 
73
-	     /* We are called from child_init, process_count has definitive
73
+	     /* We are called from child_init, estimated_process_count has definitive
74 74
 	      * value now and thus we can safely allocate the variables
75 75
 	      */
76
-	size = sizeof(stat_counter) * process_count;
76
+	size = sizeof(stat_counter) * get_max_procs();
77 77
 	tm_stats->s_waiting = shm_malloc(size);
78 78
 	if (tm_stats->s_waiting == 0) {
79 79
 		ERR("No mem for stats\n");
... ...
@@ -135,7 +135,7 @@ void tm_rpc_stats(rpc_t* rpc, void* c)
135 135
 	unsigned long total, current, waiting, total_local;
136 136
 	int i, pno;
137 137
 
138
-	pno = process_count;
138
+	pno = get_max_procs();
139 139
 	for(i = 0, total = 0, waiting = 0, total_local = 0; i < pno; i++) {
140 140
 		total += tm_stats->s_transactions[i];
141 141
 		waiting += tm_stats->s_waiting[i];
... ...
@@ -511,7 +511,7 @@ static int mod_init(void)
511 511
 
512 512
 	     /* First tm_stat initialization function only allocates the top level stat
513 513
 	      * structure in shared memory, the initialization will complete in child
514
-	      * init with init_tm_stats_child when the final value of process_count is
514
+	      * init with init_tm_stats_child when the final value of estimated_process_count is
515 515
 	      * known
516 516
 	      */
517 517
 	if (init_tm_stats() < 0) {
... ...
@@ -32,6 +32,7 @@
32 32
  * History:
33 33
  * --------
34 34
  *  2003-04-15  added tcp_disable support (andrei)
35
+ *  2006-06-14	added process table in shared mem (dragos)
35 36
  */
36 37
 
37 38
 
... ...
@@ -40,33 +41,53 @@
40 40
 
41 41
 #include <sys/types.h>
42 42
 #include <unistd.h>
43
+#include <stdlib.h>
43 44
 
44 45
 #include "globals.h"
45 46
 #include "timer.h"
46 47
 #include "socket_info.h"
48
+#include "locking.h"
47 49
 
48
-#define MAX_PT_DESC	128
50
+#define MAX_PT_DESC			128
49 51
 
50 52
 struct process_table {
51 53
 	int pid;
52 54
 #ifdef USE_TCP
53
-	int unix_sock; /* unix socket on which tcp main listens */
54
-	int idx; /* tcp child index, -1 for other processes */
55
+	int unix_sock; 	/* unix socket on which tcp main listens	*/
56
+	int idx; 		/* tcp child index, -1 for other processes 	*/
55 57
 #endif
56 58
 	char desc[MAX_PT_DESC];
57 59
 };
58 60
 
59 61
 extern struct process_table *pt;
62
+extern gen_lock_t* process_lock;
63
+extern int *process_count;
60 64
 extern int process_no;
61
-extern int process_count;
62
-extern int last_process;
63 65
 
66
+extern struct tcp_child* tcp_children;
67
+
68
+inline int init_pt();
69
+int get_max_procs();
70
+int register_procs(int no);
64 71
 
65 72
 /* return processes pid */
66
-inline static int my_pid()
67
-{
68
-	return pt ? pt[process_no].pid : getpid();
69
-}
73
+inline int my_pid();
74
+
75
+/**
76
+ * Forks a new process.
77
+ * @param desc - text description for the process table
78
+ * @param make_sock - if to create a unix socket pair for it
79
+ * @returns the pid of the new process
80
+ */
81
+inline int fork_process(int child_id,char *desc,int make_sock);
70 82
 
83
+/**
84
+ * Forks a new TCP process.
85
+ * @param desc - text description for the process table
86
+ * @param r - index in the tcp_children array
87
+ * @param *reader_fd_1 - pointer to return the reader_fd[1]
88
+ * @returns the pid of the new process
89
+ */
90
+inline int fork_tcp_process(int child_id,char *desc,int r,int *reader_fd_1);
71 91
 
72 92
 #endif
... ...
@@ -87,6 +87,8 @@ typedef int (*param_func_t)( modparam_t type, void* val);
87 87
 #define PROC_FIFO     -2  /* FIFO attendant process */
88 88
 #define PROC_TCP_MAIN -4  /* TCP main process */
89 89
 #define PROC_UNIXSOCK -5  /* Unix socket server */
90
+#define PROC_NOCHLDINIT -128 /* no child init functions will be called
91
+                                if this rank is used in fork_process() */
90 92
 
91 93
 #define PROC_MIN PROC_UNIXSOCK /* Minimum process rank */
92 94
 
... ...
@@ -29,12 +29,22 @@
29 29
 #define tcp_init_h
30 30
 #include "ip_addr.h"
31 31
 
32
+struct tcp_child{
33
+	pid_t pid;
34
+	int proc_no; /* ser proc_no, for debugging */
35
+	int unix_sock; /* unix "read child" sock fd */
36
+	int busy;
37
+	int n_reqs; /* number of requests serviced so far */
38
+};
39
+
40
+
32 41
 int init_tcp();
33 42
 void destroy_tcp();
34 43
 int tcp_init(struct socket_info* sock_info);
35 44
 int tcp_init_children();
36 45
 void tcp_main_loop();
37 46
 void tcp_receive_loop(int unix_sock);
47
+int tcp_fix_child_sockets(int* fd);
38 48
 
39 49
 
40 50
 #endif
... ...
@@ -149,14 +149,6 @@
149 149
 enum fd_types { F_NONE, F_SOCKINFO /* a tcp_listen fd */,
150 150
 				F_TCPCONN, F_TCPCHILD, F_PROC };
151 151
 
152
-struct tcp_child{
153
-	pid_t pid;
154
-	int proc_no; /* ser proc_no, for debugging */
155
-	int unix_sock; /* unix "read child" sock fd */
156
-	int busy;
157
-	int n_reqs; /* number of requests serviced so far */
158
-};
159
-
160 152
 
161 153
 
162 154
 int tcp_accept_aliases=0; /* by default don't accept aliases */
... ...
@@ -175,7 +167,7 @@ struct tcp_conn_alias** tcpconn_aliases_hash=0;
175 175
 struct tcp_connection** tcpconn_id_hash=0;
176 176
 gen_lock_t* tcpconn_lock=0;
177 177
 
178
-static struct tcp_child* tcp_children;
178
+struct tcp_child* tcp_children;
179 179
 static int* connection_id=0; /*  unique for each connection, used for 
180 180
 								quickly finding the corresponding connection
181 181
 								for a reply */
... ...
@@ -1919,7 +1911,7 @@ error:
1919 1919
 }
1920 1920
 
1921 1921
 
1922
-
1922
+#ifdef TCP_CHILD_NON_BLOCKING
1923 1923
 /* returns -1 on error */
1924 1924
 static int set_non_blocking(int s)
1925 1925
 {
... ...
@@ -1941,14 +1933,28 @@ error:
1941 1941
 	return -1;
1942 1942
 }
1943 1943
 
1944
+#endif
1945
+
1946
+
1947
+/*  returns -1 on error, 0 on success */
1948
+int tcp_fix_child_sockets(int* fd)
1949
+{
1950
+#ifdef TCP_CHILD_NON_BLOCKING
1951
+	if ((set_non_blocking(fd[0])<0) ||
1952
+		(set_non_blocking(fd[1])<0)){
1953
+		return -1;
1954
+	}
1955
+#endif
1956
+	return 0;
1957
+}
1958
+
1944 1959
 
1945 1960
 
1946 1961
 /* starts the tcp processes */
1947 1962
 int tcp_init_children()
1948 1963
 {
1949 1964
 	int r;
1950
-	int sockfd[2];
1951
-	int reader_fd[2]; /* for comm. with the tcp children read  */
1965
+	int reader_fd_1; /* for comm. with the tcp children read  */
1952 1966
 	pid_t pid;
1953 1967
 	struct socket_info *si;
1954 1968
 	
... ...
@@ -1962,11 +1968,11 @@ int tcp_init_children()
1962 1962
 		for (si=tls_listen; si; si=si->next, r++);
1963 1963
 #endif
1964 1964
 	
1965
-	tcp_max_fd_no=process_count*2 +r-1 /* timer */ +3; /* stdin/out/err*/
1966
-	/* max connections can be temporarily exceeded with process_count
1965
+	tcp_max_fd_no=get_max_procs()*2 +r-1 /* timer */ +3; /* stdin/out/err*/
1966
+	/* max connections can be temporarily exceeded with estimated_process_count
1967 1967
 	 * - tcp_main (tcpconn_connect called simultaneously in all all the 
1968 1968
 	 *  processes) */
1969
-	tcp_max_fd_no+=tcp_max_connections+process_count-1 /* tcp main */;
1969
+	tcp_max_fd_no+=tcp_max_connections+get_max_procs()-1 /* tcp main */;
1970 1970
 	
1971 1971
 	/* alloc the children array */
1972 1972
 	tcp_children=pkg_malloc(sizeof(struct tcp_child)*tcp_children_no);
... ...
@@ -1979,60 +1985,19 @@ int tcp_init_children()
1979 1979
 	
1980 1980
 	/* fork children & create the socket pairs*/
1981 1981
 	for(r=0; r<tcp_children_no; r++){
1982
-		if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
1983
-			LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1984
-					strerror(errno));
1985
-			goto error;
1986
-		}
1987
-		if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
1988
-			LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1989
-					strerror(errno));
1990
-			goto error;
1991
-		}
1992
-#ifdef TCP_CHILD_NON_BLOCKING
1993
-		if ((set_non_blocking(reader_fd[0])<0) || 
1994
-			(set_non_blocking(reader_fd[1])<0)){
1995
-			LOG(L_ERR, "ERROR: tcp_main: failed to set non blocking"
1996
-						"on child sockets\n");
1997
-			/* continue, it's not critical (it will go slower under
1998
-			 * very high connection rates) */
1999
-		}
2000
-#endif
2001
-		
2002
-		process_no++;
2003 1982
 		child_rank++;
2004
-		pid=fork();
1983
+		pid=fork_tcp_process(child_rank,"tcp receiver",1,&reader_fd_1);
2005 1984
 		if (pid<0){
2006 1985
 			LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
2007 1986
 					strerror(errno));
2008 1987
 			goto error;
2009 1988
 		}else if (pid>0){
2010 1989
 			/* parent */
2011
-			close(sockfd[1]);
2012
-			close(reader_fd[1]);
2013
-			tcp_children[r].pid=pid;
2014
-			tcp_children[r].proc_no=process_no;
2015
-			tcp_children[r].busy=0;
2016
-			tcp_children[r].n_reqs=0;
2017
-			tcp_children[r].unix_sock=reader_fd[0];
2018
-			pt[process_no].pid=pid;
2019
-			pt[process_no].unix_sock=sockfd[0];
2020
-			pt[process_no].idx=r;
2021
-			strncpy(pt[process_no].desc, "tcp receiver", MAX_PT_DESC);
2022 1990
 		}else{
2023 1991
 			/* child */
2024
-			close(sockfd[0]);
2025
-			unix_tcp_sock=sockfd[1];
2026 1992
 			bind_address=0; /* force a SEGFAULT if someone uses a non-init.
2027 1993
 							   bind address on tcp */
2028
-			/* record pid twice to avoid the child using it, before
2029
-			 * parent gets a chance to set it*/
2030
-			pt[process_no].pid=getpid();
2031
-			if (init_child(child_rank) < 0) {
2032
-				LOG(L_ERR, "init_children failed\n");
2033
-				goto error;
2034
-			}
2035
-			tcp_receive_loop(reader_fd[1]);
1994
+			tcp_receive_loop(reader_fd_1);
2036 1995
 		}
2037 1996
 	}
2038 1997
 	return 0;