Browse Source

- changed signal handling, added an attendant process

Andrei Pelinescu-Onciul 23 năm trước cách đây
mục cha
commit
6e94f57f2d
4 tập tin đã thay đổi với 152 bổ sung95 xóa
  1. 1 1
      Makefile.defs
  2. 147 91
      main.c
  3. 3 2
      test/stateless.cfg
  4. 1 1
      test/th-uri-2.cfg

+ 1 - 1
Makefile.defs

@@ -8,7 +8,7 @@
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL = 7
-EXTRAVERSION = -3-ipv6
+EXTRAVERSION = -4-ipv6
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s)

+ 147 - 91
main.c

@@ -204,6 +204,7 @@ unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
 int children_no = 0;			/* number of children processing requests */
 int *pids=0;					/*array with childrens pids, 0= main proc,
 									alloc'ed in shared mem if possible*/
+int sig_flag = 0;              /* last signal received */
 int debug = 0;
 int dont_fork = 0;
 int log_stderr = 0;
@@ -355,6 +356,92 @@ error:
 
 
 
+void handle_sigs()
+{
+	pid_t	chld;
+	int	chld_status;
+
+	switch(sig_flag){
+		case 0: break; /* do nothing*/
+		case SIGINT:
+		case SIGPIPE:
+		case SIGTERM:
+			/* we end the program in all these cases */
+			if (sig_flag==SIGINT)
+				DBG("INT received, program terminates\n");
+			else if (sig_flag==SIGPIPE)
+				DBG("SIGPIPE rreceived, program terminates\n");
+			else
+				DBG("SIGTERM received, program terminates\n");
+				
+			destroy_modules();
+#ifdef PKG_MALLOC
+			LOG(L_INFO, "Memory status (pkg):\n");
+			pkg_status();
+#endif
+#ifdef SHM_MEM
+			LOG(L_INFO, "Memory status (shm):\n");
+			shm_status();
+			/* zero all shmem alloc vars that we still use */
+			pids=0;
+			shm_mem_destroy();
+#endif
+			if (pid_file) unlink(pid_file);
+			/* kill children also*/
+			kill(0, SIGTERM);
+			dprint("Thank you for flying " NAME "\n");
+			exit(0);
+			break;
+			
+		case SIGUSR1:
+#ifdef STATS
+			dump_all_statistic();
+#endif
+#ifdef PKG_MALLOC
+			LOG(L_INFO, "Memory status (pkg):\n");
+			pkg_status();
+#endif
+#ifdef SHM_MEM
+			LOG(L_INFO, "Memory status (shm):\n");
+			shm_status();
+#endif
+			break;
+			
+		case SIGCHLD:
+			while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
+				if (WIFEXITED(chld_status)) 
+					LOG(L_INFO, "child process %d exited normally,"
+							" status=%d\n", chld, 
+							WEXITSTATUS(chld_status));
+				else if (WIFSIGNALED(chld_status)) {
+					LOG(L_INFO, "child process %d exited by a signal"
+							" %d\n", chld, WTERMSIG(chld_status));
+#ifdef WCOREDUMP
+					LOG(L_INFO, "core was %sgenerated\n",
+							 WCOREDUMP(chld_status) ?  "" : "not" );
+#endif
+				}else if (WIFSTOPPED(chld_status)) 
+					LOG(L_INFO, "child process %d stopped by a"
+								" signal %d\n", chld,
+								 WSTOPSIG(chld_status));
+			}
+			/* exit */
+			kill(0, SIGTERM);
+			DBG("terminating due to SIGCHLD\n");
+			exit(0);
+			break;
+		
+		case SIGHUP: /* ignoring it*/
+					DBG("SIGHUP received, ignoring it\n");
+					break;
+		default:
+			LOG(L_CRIT, "WARNING: unhandled signal %d\n", sig_flag);
+	}
+	sig_flag=0;
+}
+
+
+
 /* main loop */
 int main_loop()
 {
@@ -458,21 +545,33 @@ int main_loop()
 	pids[process_no]=getpid();
 	process_bit = 0;
 	is_main=1;
-	bind_address=&sock_info[0]; /* main proc -> it shoudln't send anything, if it does */
-	bind_idx=0;					/*   it will use the first address */
+	bind_address=&sock_info[0]; /* main proc -> it shoudln't send anything, */
+	bind_idx=0;					/* if it does it will use the first address */
 
 	if (timer_list){
-		for(;;){
-			/* debug:  instead of doing something usefull */
-			/* (placeholder for timers, etc.) */
-			sleep(TIMER_TICK);
-			/* if we received a signal => TIMER_TICK may have not elapsed*/
-			timer_ticker();
+		/* fork again for the attendant process*/
+		if ((pid=fork())<0){
+			LOG(L_CRIT, "main_loop: cannot fork timer process\n");
+			goto error;
+		}else if (pid==0){
+			/* child */
+			is_main=0; /* warning: we don't keep this process pid*/
+			for(;;){
+				/* debug:  instead of doing something usefull */
+				/* (placeholder for timers, etc.) */
+				sleep(TIMER_TICK);
+				/* if we received a signal => TIMER_TICK may have not elapsed*/
+				timer_ticker();
+			}
 		}
-	}else{
-		for(;;) pause(); 
 	}
 	
+	for(;;){
+			pause();
+			handle_sigs();
+	}
+	
+	
 	/*return 0; */
  error:
 	return -1;
@@ -483,94 +582,41 @@ int main_loop()
 /* added by jku; allows for regular exit on a specific signal;
    good for profiling which only works if exited regularly and
    not by default signal handlers
+    - modified by andrei: moved most of the stuff to handle_sigs, 
+       made it safer for the "fork" case
 */
 static void sig_usr(int signo)
 {
-	pid_t	chld;
-	int	chld_status;
 
-	/* XXX Need to doublecheck .... handler fo SIGINT quite different
-	   from SIGTERM handler ... in SIGTERM_h, thinkgs such as
-	   destroy_modules and shm_destroy are missing ... is that really ok?
-	   THX -Jiri
-	*/
-	if (signo==SIGINT || signo==SIGPIPE) {	/* exit gracefuly */
-		DPrint("INT received, program terminates\n");
-#		ifdef _OBSOLETED_STATS
-		/* print statistics on exit only for the first process */
-		if (stats->process_index==0 && stat_file )
-			if (dump_all_statistic()==0)
-				printf("statistic dumped to %s\n", stat_file );
-			else
-				printf("statistics dump to %s failed\n", stat_file );
-#		endif
-		/* WARNING: very dangerous, might be unsafe*/
-		if (is_main)
-			destroy_modules();
-#ifdef PKG_MALLOC
-		LOG(L_INFO, "Memory status (pkg):\n");
-		pkg_status();
-#		endif
-#ifdef SHM_MEM
-		if (is_main){
-			LOG(L_INFO, "Memory status (shm):\n");
-			shm_status();
-			/*zero all shmem  alloc vars, that will still use*/
-			pids=0;
-			shm_mem_destroy();
-		}
-#endif
-		dprint("Thank you for flying " NAME "\n");
-		/* kill children also*/
-		kill(0, SIGTERM);
-		exit(0);
-	} else if (signo==SIGTERM) { /* exit gracefully as daemon */
-		DPrint("TERM received, program terminates\n");
-		if (is_main){
-#ifdef _OBSOLETED_STATS
-			dump_all_statistic();
-#endif
-			if (pid_file) {
-				unlink(pid_file);
-			}
-		}
-		kill(0, SIGTERM);
-		exit(0);
-	} else if (signo==SIGUSR1) { /* statistic */
-#ifdef STATS
-		dump_all_statistic();
-#endif
-#ifdef PKG_MALLOC
-		LOG(L_INFO, "Memory status (pkg):\n");
-		pkg_status();
-#endif
-#ifdef SHM_MEM
-		LOG(L_INFO, "Memory status (shm):\n");
-		shm_status();
-#endif
-	} else if (signo==SIGCHLD) {
-		while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
-			if (WIFEXITED(chld_status)) 
-				LOG(L_INFO, "child process %d exited normally, status=%d\n",
-					chld, WEXITSTATUS(chld_status));
-			else if (WIFSIGNALED(chld_status)) {
-				LOG(L_INFO, "child process %d exited by a signal %d\n",
-					chld, WTERMSIG(chld_status));
-#				ifdef WCOREDUMP
-				LOG(L_INFO, "core was %sgenerated\n", WCOREDUMP(chld_status) ?
-					"" : "not" );
-#				endif
-			} else if (WIFSTOPPED(chld_status)) 
-				LOG(L_INFO, "child process %d stopped by a signal %d\n",
-					chld, WSTOPSIG(chld_status));
+	if (is_main){
+		if (sig_flag==0) sig_flag=signo;
+		else /*  previous sig. not processed yet, ignoring? */
+			return; ;
+		if (dont_fork) 
+				/* only one proc, dooing everything from the sig handler,
+				unsafe, but this is only for debugging mode*/
+			handle_sigs();
+	}else{
+		/* process the important signals */
+		switch(signo){
+			case SIGINT:
+			case SIGPIPE:
+			case SIGTERM:
+					exit(0);
+					break;
+			case SIGUSR1:
+				/* statistics, do nothing, printed only from the main proc */
+					break;
+				/* ignored*/
+			case SIGUSR2:
+			case SIGHUP:
+					break;
 		}
-		/* exit */
-		kill(0, SIGTERM);
-		exit(0);
 	}
 }
 
 
+
 void test();
 
 int main(int argc, char** argv)
@@ -608,6 +654,16 @@ int main(int argc, char** argv)
 		DPrint("ERROR: no SIGTERM signal handler can be installed\n");
 		goto error;
 	}
+	if (signal(SIGHUP , sig_usr)  == SIG_ERR ) {
+		DPrint("ERROR: no SIGHUP signal handler can be installed\n");
+		goto error;
+	}
+	if (signal(SIGUSR2 , sig_usr)  == SIG_ERR ) {
+		DPrint("ERROR: no SIGUSR2 signal handler can be installed\n");
+		goto error;
+	}
+
+
 
 	/* process command line (get port no, cfg. file path etc) */
 	opterr=0;
@@ -873,8 +929,8 @@ int main(int argc, char** argv)
 						sock_info[r].port_no);
 			goto error;
 		}
-		/* on some system snprintf return really strange things if it does not 
-			have  enough space */
+		/* on some systems snprintf returns really strange things if it does 
+		  not have  enough space */
 		port_no_str_len=
 				(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
 		sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1);

+ 3 - 2
test/stateless.cfg

@@ -8,12 +8,12 @@
 debug=9          # debug level (cmd line: -dddddddddd)
 #fork=yes          # (cmd. line: -D)
 fork=yes
-fork=no
+#fork=no
 log_stderror=yes # (cmd line: -E)
 #log_stderror=no	# (cmd line: -E)
 
 
-children=1
+children=10
 check_via=no     # (cmd. line: -v)
 dns=off           # (cmd. line: -r)
 rev_dns=off      # (cmd. line: -R)
@@ -26,6 +26,7 @@ loop_checks=0
 # for more info: sip_router -h
 
 #modules
+loadmodule "modules/tm/tm.so"
 
 
 route{

+ 1 - 1
test/th-uri-2.cfg

@@ -22,7 +22,7 @@ rev_dns=yes      # (cmd. line: -R)
 #port=5070
 #listen=127.0.0.1
 #listen=192.168.57.33
-listen=192.168.57.72
+#listen=192.168.57.72
 #listen=10.0.0.179
 loop_checks=0
 # for more info: sip_router -h