[git commit] inetd: close new udp fd in "udp nowait" case

Denys Vlasenko vda.linux at googlemail.com
Sun Sep 11 14:48:21 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=223b9417b3789e60f3a91510661b00a92c0db027
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/inetd.c |   66 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/networking/inetd.c b/networking/inetd.c
index 873fd95..fc6847b 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -357,10 +357,26 @@ struct BUG_G_too_big {
 	config_filename = "/etc/inetd.conf"; \
 } while (0)
 
+#if 1
+# define dbg(...) ((void)0)
+#else
+# define dbg(...) \
+do { \
+	int dbg_fd = open("inetd_debug.log", O_WRONLY | O_CREAT | O_APPEND, 0666); \
+	if (dbg_fd >= 0) { \
+		fdprintf(dbg_fd, "%d: ", getpid()); \
+		fdprintf(dbg_fd, __VA_ARGS__); \
+		close(dbg_fd); \
+	} \
+} while (0)
+#endif
+
 static void maybe_close(int fd)
 {
-	if (fd >= 0)
+	if (fd >= 0) {
 		close(fd);
+		dbg("closed fd:%d\n", fd);
+	}
 }
 
 // TODO: move to libbb?
@@ -464,7 +480,9 @@ static void remove_fd_from_set(int fd)
 {
 	if (fd >= 0) {
 		FD_CLR(fd, &allsock);
+		dbg("stopped listening on fd:%d\n", fd);
 		maxsock = -1;
+		dbg("maxsock:%d\n", maxsock);
 	}
 }
 
@@ -472,8 +490,10 @@ static void add_fd_to_set(int fd)
 {
 	if (fd >= 0) {
 		FD_SET(fd, &allsock);
+		dbg("started listening on fd:%d\n", fd);
 		if (maxsock >= 0 && fd > maxsock) {
 			prev_maxsock = maxsock = fd;
+			dbg("maxsock:%d\n", maxsock);
 			if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
 				bump_nofile();
 		}
@@ -492,6 +512,7 @@ static void recalculate_maxsock(void)
 			maxsock = fd;
 		fd++;
 	}
+	dbg("recalculated maxsock:%d\n", maxsock);
 	prev_maxsock = maxsock;
 	if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
 		bump_nofile();
@@ -549,8 +570,13 @@ static void prepare_socket_fd(servtab_t *sep)
 		rearm_alarm();
 		return;
 	}
-	if (sep->se_socktype == SOCK_STREAM)
+
+	if (sep->se_socktype == SOCK_STREAM) {
 		listen(fd, global_queuelen);
+		dbg("new sep->se_fd:%d (stream)\n", fd);
+	} else {
+		dbg("new sep->se_fd:%d (!stream)\n", fd);
+	}
 
 	add_fd_to_set(fd);
 	sep->se_fd = fd;
@@ -1012,7 +1038,7 @@ static void reread_config_file(int sig UNUSED_PARAM)
 	 * new config file doesnt have them. */
 	block_CHLD_HUP_ALRM(&omask);
 	sepp = &serv_list;
-	while ((sep = *sepp)) {
+	while ((sep = *sepp) != NULL) {
 		if (sep->se_checked) {
 			sepp = &sep->se_next;
 			continue;
@@ -1206,11 +1232,13 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 			}
 			continue;
 		}
+		dbg("ready_fd_cnt:%d\n", ready_fd_cnt);
 
 		for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
 			if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
 				continue;
 
+			dbg("ready fd:%d\n", sep->se_fd);
 			ready_fd_cnt--;
 			ctrl = sep->se_fd;
 			accepted_fd = -1;
@@ -1218,6 +1246,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 			if (!sep->se_wait) {
 				if (sep->se_socktype == SOCK_STREAM) {
 					ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
+					dbg("accepted_fd:%d\n", accepted_fd);
 					if (ctrl < 0) {
 						if (errno != EINTR)
 							bb_perror_msg("accept (for %s)", sep->se_service);
@@ -1238,19 +1267,22 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
  * (can create many copies of same child, etc).
  * Parent must create and use new socket instead. */
 					new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
+					dbg("new_udp_fd:%d\n", new_udp_fd);
 					if (new_udp_fd < 0) { /* error: eat packet, forget about it */
  udp_err:
 						recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT);
 						continue;
 					}
 					setsockopt_reuseaddr(new_udp_fd);
-					/* TODO: better do bind after vfork in parent,
+					/* TODO: better do bind after fork in parent,
 					 * so that we don't have two wildcard bound sockets
 					 * even for a brief moment? */
 					if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
+						dbg("bind(new_udp_fd) failed\n");
 						close(new_udp_fd);
 						goto udp_err;
 					}
+					dbg("bind(new_udp_fd) succeeded\n");
 				}
 			}
 
@@ -1278,6 +1310,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 							sep->se_count = 0;
 							rearm_alarm(); /* will revive it in RETRYTIME sec */
 							restore_sigmask(&omask);
+							maybe_close(new_udp_fd);
 							maybe_close(accepted_fd);
 							continue; /* -> check next fd in fd set */
 						}
@@ -1298,17 +1331,18 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 					bb_perror_msg("vfork"+1);
 					sleep(1);
 					restore_sigmask(&omask);
+					maybe_close(new_udp_fd);
 					maybe_close(accepted_fd);
 					continue; /* -> check next fd in fd set */
 				}
 				if (pid == 0)
 					pid--; /* -1: "we did fork and we are child" */
 			}
-			/* if pid == 0 here, we never forked */
+			/* if pid == 0 here, we didn't fork */
 
 			if (pid > 0) { /* parent */
 				if (sep->se_wait) {
-					/* tcp wait: we passed listening socket to child,
+					/* wait: we passed socket to child,
 					 * will wait for child to terminate */
 					sep->se_wait = pid;
 					remove_fd_from_set(sep->se_fd);
@@ -1317,17 +1351,19 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 					/* udp nowait: child connected the socket,
 					 * we created and will use new, unconnected one */
 					xmove_fd(new_udp_fd, sep->se_fd);
+					dbg("moved new_udp_fd:%d to sep->se_fd:%d\n", new_udp_fd, sep->se_fd);
 				}
 				restore_sigmask(&omask);
 				maybe_close(accepted_fd);
 				continue; /* -> check next fd in fd set */
 			}
 
-			/* we are either child or didn't vfork at all */
+			/* we are either child or didn't fork at all */
 #ifdef INETD_BUILTINS_ENABLED
 			if (sep->se_builtin) {
-				if (pid) { /* "pid" is -1: we did vfork */
+				if (pid) { /* "pid" is -1: we did fork */
 					close(sep->se_fd); /* listening socket */
+					dbg("closed sep->se_fd:%d\n", sep->se_fd);
 					logmode = LOGMODE_NONE; /* make xwrite etc silent */
 				}
 				restore_sigmask(&omask);
@@ -1335,7 +1371,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 					sep->se_builtin->bi_stream_fn(ctrl, sep);
 				else
 					sep->se_builtin->bi_dgram_fn(ctrl, sep);
-				if (pid) /* we did vfork */
+				if (pid) /* we did fork */
 					_exit(EXIT_FAILURE);
 				maybe_close(accepted_fd);
 				continue; /* -> check next fd in fd set */
@@ -1345,9 +1381,14 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 			setsid();
 			/* "nowait" udp */
 			if (new_udp_fd >= 0) {
-				len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family);
+				len_and_sockaddr *lsa;
+				int r;
+
+				close(new_udp_fd);
+				dbg("closed new_udp_fd:%d\n", new_udp_fd);
+				lsa = xzalloc_lsa(sep->se_family);
 				/* peek at the packet and remember peer addr */
-				int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
+				r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
 					&lsa->u.sa, &lsa->len);
 				if (r < 0)
 					goto do_exit1;
@@ -1355,6 +1396,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 				 * only packets from this peer will be recv'ed,
 				 * and bare write()/send() will work on it */
 				connect(ctrl, &lsa->u.sa, lsa->len);
+				dbg("connected ctrl:%d to remote peer\n", ctrl);
 				free(lsa);
 			}
 			/* prepare env and exec program */
@@ -1391,6 +1433,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 			 */
 			xmove_fd(ctrl, STDIN_FILENO);
 			xdup2(STDIN_FILENO, STDOUT_FILENO);
+			dbg("moved ctrl:%d to fd 0,1[,2]\n", ctrl);
 			/* manpages of inetd I managed to find either say
 			 * that stderr is also redirected to the network,
 			 * or do not talk about redirection at all (!) */
@@ -1403,6 +1446,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 					maybe_close(sep2->se_fd);
 			sigaction_set(SIGPIPE, &saved_pipe_handler);
 			restore_sigmask(&omask);
+			dbg("execing:'%s'\n", sep->se_program);
 			BB_EXECVP(sep->se_program, sep->se_argv);
 			bb_perror_msg("can't execute '%s'", sep->se_program);
  do_exit1:
-- 
1.7.3.4



More information about the busybox-cvs mailing list