Bladeren bron

- init_childs(PROC_MAIN) moved before starting tcp_main to allow possible
tcp usage from module started processes
- fork_process() sanity checks & debugging: fail & log a bug if called
with make_sock==1 from a process != main or if called after tcp was
started; reset is_main for children
- fork_tcp_process() sanity checks as above
- init_pt(): initialize tcp comm. fds to -1, fix description writing
for main/attendant.

Andrei Pelinescu-Onciul 19 jaren geleden
bovenliggende
commit
f2e1aa5002
4 gewijzigde bestanden met toevoegingen van 59 en 28 verwijderingen
  1. 1 1
      Makefile.defs
  2. 1 0
      globals.h
  3. 18 23
      main.c
  4. 39 4
      pt.c

+ 1 - 1
Makefile.defs

@@ -67,7 +67,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev54-tm_fixes
+EXTRAVERSION = -dev55-tm_fixes
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 			$(SUBLEVEL) )

+ 1 - 0
globals.h

@@ -76,6 +76,7 @@ extern struct socket_info* sendipv6_tls; /* same as above for ipv6 */
 extern unsigned int maxbuffer;
 extern int children_no;
 #ifdef USE_TCP
+extern int tcp_main_pid;
 extern int tcp_children_no;
 extern int tcp_disable;
 extern int tcp_accept_aliases;

+ 18 - 23
main.c

@@ -64,8 +64,10 @@
  *  2006-07-13  added dns cache/failover init. (andrei)
  *  2006-10-13  added global variables stun_refresh_interval, stun_allow_stun
  *               and stun_allow_fp (vlada)
- *  2006-10-25  don't log messages from signal hanlders if NO_SIG_DEBUG is
+ *  2006-10-25  don't log messages from signal handlers if NO_SIG_DEBUG is
  *               defined; improved exit kill timeout (andrei)
+ *              init_childs(PROC_MAIN) before starting tcp_main, to allow
+ *               tcp usage for module started processes (andrei)
  */
 
 
@@ -341,6 +343,7 @@ int addresses_no=0;                   /* number of names/ips */
 #endif
 struct socket_info* udp_listen=0;
 #ifdef USE_TCP
+int tcp_main_pid=0; /* set after the tcp main process is started */
 struct socket_info* tcp_listen=0;
 #endif
 #ifdef USE_TLS
@@ -489,7 +492,7 @@ static void kill_all_children(int signum)
 
 
 
-/* if this handler is called, a critical timeout has occured while
+/* if this handler is called, a critical timeout has occurred while
  * waiting for the children to finish => we should kill everything and exit */
 static void sig_alarm_kill(int signo)
 {
@@ -501,7 +504,7 @@ static void sig_alarm_kill(int signo)
 }
 
 
-/* like sig_alarm_kill, but the timeout has occured when cleaning up
+/* like sig_alarm_kill, but the timeout has occurred when cleaning up
  * => try to leave a core for future diagnostics */
 static void sig_alarm_abort(int signo)
 {
@@ -848,8 +851,6 @@ int main_loop()
 #endif
 
 	/* one "main" process and n children handling i/o */
-
-	is_main=0;
 	if (dont_fork){
 #ifdef STATS
 		setstats( 0 );
@@ -922,10 +923,6 @@ int main_loop()
 			LOG(L_ERR, "main_dontfork: init_child failed\n");
 			goto error;
 		}
-
-		is_main=1; /* hack 42: call init_child with is_main=0 in case
-					 some modules wants to fork a child */
-
 		return udp_rcv_loop();
 	}else{
 
@@ -1018,7 +1015,6 @@ int main_loop()
 			goto error;
 		}else if (pid==0){
 			/* child */
-			/* is_main=0; */
 			if (arm_slow_timer()<0) goto error;
 			slow_timer_main();
 		}else{
@@ -1033,12 +1029,20 @@ int main_loop()
 			goto error;
 		}else if (pid==0){
 			/* child */
-			/* is_main=0; */
 			if (arm_timer()<0) goto error;
 			timer_main();
 		}else{
 		}
 	}
+
+/* init childs with rank==MAIN before starting tcp main (in case they want to 
+ *  fork  a tcp capable process, the corresponding tcp. comm. fds in pt[] must
+ *  be set before calling tcp_main_loop()) */
+	if (init_child(PROC_MAIN) < 0) {
+		LOG(L_ERR, "main: error in init_child\n");
+		goto error;
+	}
+
 #ifdef USE_TCP
 		if (!tcp_disable){
 				/* start tcp  & tls receivers */
@@ -1053,6 +1057,7 @@ int main_loop()
 				/* child */
 				tcp_main_loop();
 			}else{
+				tcp_main_pid=pid;
 				unix_tcp_sock=-1;
 			}
 		}
@@ -1061,20 +1066,10 @@ int main_loop()
 	strncpy(pt[0].desc, "attendant", MAX_PT_DESC );
 #ifdef USE_TCP
 	if(!tcp_disable){
-		pt[process_no].unix_sock=-1;
-		pt[process_no].idx=-1; /* this is not a "tcp" process*/
+		/* main's tcp sockets are disabled by default from init_pt() */
 		unix_tcp_sock=-1;
 	}
 #endif
-	/*DEBUG- remove it*/
-
-	/* process_bit = 0; */
-	is_main=1;
-
-	if (init_child(PROC_MAIN) < 0) {
-		LOG(L_ERR, "main: error in init_child\n");
-		goto error;
-	}
 
 	/*DEBUG- remove it*/
 #ifdef EXTRA_DEBUG
@@ -1091,7 +1086,7 @@ int main_loop()
 
 	/*return 0; */
  error:
-	is_main=1;  /* if we are here, we are the "main process",
+				 /* if we are here, we are the "main process",
 				  any forked children should exit with exit(-1) and not
 				  ever use return */
 	return -1;

+ 39 - 4
pt.c

@@ -33,6 +33,8 @@
  * --------
  *  2006-06-14	added process table in shared mem (dragos)
  *  2006-09-20	added profile support (-DPROFILING) (hscholz)
+ *  2006-10-25	sanity check before allowing forking w/ tcp support (is_main
+ *               & tcp not started yet); set is_main=0 in childs (andrei)
  */
 
 
@@ -60,6 +62,10 @@ static int estimated_proc_no=0;
 /* returns 0 on success, -1 on error */
 int init_pt(int proc_no)
 {
+#ifdef USE_TCP
+	int r;
+#endif
+	
 	estimated_proc_no+=proc_no;
 	/*alloc pids*/
 #ifdef SHM_MEM
@@ -76,10 +82,15 @@ int init_pt(int proc_no)
 		return -1;
 	}
 	memset(pt, 0, sizeof(struct process_table)*estimated_proc_no);
-
+#ifdef USE_TCP
+	for (r=0; r<estimated_proc_no; r++){
+		pt[r].unix_sock=-1;
+		pt[r].idx=-1;
+	}
+#endif
 	process_no=0; /*main process number*/
 	pt[process_no].pid=getpid();
-	memcpy(pt[*process_count].desc,"main",5);
+	memcpy(pt[process_no].desc,"main",5);
 	*process_count=1;
 	return 0;
 }
@@ -136,6 +147,18 @@ int fork_process(int child_id, char *desc, int make_sock)
 	#ifdef USE_TCP
 		sockfd[0]=sockfd[1]=-1;
 		if(make_sock && !tcp_disable){
+			 if (!is_main){
+				 LOG(L_CRIT, "BUG: fork_process(..., 1) called from a non "
+						 "\"main\" process! If forking from a module's "
+						 "child_init() fork only if rank==PROC_MAIN or"
+						 " give up tcp send support (use 0 for make_sock)\n");
+				 goto error;
+			 }
+			 if (tcp_main_pid){
+				 LOG(L_CRIT, "BUG: fork_process(..., 1) called, but tcp main "
+						 " is already started\n");
+				 goto error;
+			 }
 			 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
 				LOG(L_ERR, "ERROR: fork_process(): socketpair failed: %s\n",
 							strerror(errno));
@@ -160,6 +183,7 @@ int fork_process(int child_id, char *desc, int make_sock)
 		goto error;
 	}else if (pid==0){
 		/* child */
+		is_main=0; /* a forked process cannot be the "main" one */
 		process_no=child_process_no;
 #ifdef PROFILING
 		monstartup((u_long) &_start, (u_long) &etext);
@@ -173,7 +197,7 @@ int fork_process(int child_id, char *desc, int make_sock)
 		 * this is actually relevant as the parent updates
 		 * the pt & process_count. */
 		lock_get(process_lock);
-		lock_release(process_lock);	
+		lock_release(process_lock);
 #endif
 		#ifdef USE_TCP
 			if (make_sock && !tcp_disable){
@@ -203,7 +227,7 @@ int fork_process(int child_id, char *desc, int make_sock)
 			if (make_sock && !tcp_disable){
 				close(sockfd[1]);
 				pt[child_process_no].unix_sock=sockfd[0];
-				pt[child_process_no].idx=-1; /* this is not "tcp" process*/
+				pt[child_process_no].idx=-1; /* this is not a "tcp" process*/
 			}
 		#endif
 #ifdef FORK_DONT_WAIT
@@ -242,6 +266,16 @@ int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
 	reader_fd[0]=reader_fd[1]=-1;
 	ret=-1;
 	
+	if (!is_main){
+		 LOG(L_CRIT, "BUG: fork_tcp_process() called from a non \"main\" "
+				 	"process\n");
+		 goto error;
+	 }
+	 if (tcp_main_pid){
+		 LOG(L_CRIT, "BUG: fork_tcp_process(..., 1) called _after_ starting"
+				 	" tcp main\n");
+		 goto error;
+	 }
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
 		LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
 					strerror(errno));
@@ -276,6 +310,7 @@ int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
 		goto end;
 	}
 	if (pid==0){
+		is_main=0; /* a forked process cannot be the "main" one */
 		process_no=child_process_no;
 #ifdef PROFILING
 		monstartup((u_long) &_start, (u_long) &etext);