Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Oct 2012 16:07:53 +0000 (UTC)
From:      "David E. O'Brien" <obrien@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r242142 - in stable/9: sys/dev/filemon tools/regression/filemon
Message-ID:  <201210261607.q9QG7raE035736@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: obrien
Date: Fri Oct 26 16:07:53 2012
New Revision: 242142
URL: http://svn.freebsd.org/changeset/base/242142

Log:
  MFC: r242137: Iterate rather than use recursion.  We can blow out the
       kernel stack if there is a long chain of fork(2)s.

Added:
  stable/9/tools/regression/filemon/timed-forkb.c
     - copied unchanged from r242137, head/tools/regression/filemon/timed-forkb.c
Modified:
  stable/9/sys/dev/filemon/filemon_wrapper.c
  stable/9/tools/regression/filemon/Makefile
Directory Properties:
  stable/9/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)
  stable/9/tools/   (props changed)

Modified: stable/9/sys/dev/filemon/filemon_wrapper.c
==============================================================================
--- stable/9/sys/dev/filemon/filemon_wrapper.c	Fri Oct 26 16:06:26 2012	(r242141)
+++ stable/9/sys/dev/filemon/filemon_wrapper.c	Fri Oct 26 16:07:53 2012	(r242142)
@@ -82,15 +82,14 @@ filemon_pid_check(struct proc *p)
 {
 	struct filemon *filemon;
 
-	TAILQ_FOREACH(filemon, &filemons_inuse, link) {
-		if (p->p_pid == filemon->pid)
-			return (filemon);
+	while (p->p_pptr) {
+		TAILQ_FOREACH(filemon, &filemons_inuse, link) {
+			if (p->p_pid == filemon->pid)
+				return (filemon);
+		}
+		p = p->p_pptr;
 	}
-
-	if (p->p_pptr == NULL)
-		return (NULL);
-
-	return (filemon_pid_check(p->p_pptr));
+	return (NULL);
 }
 
 static void

Modified: stable/9/tools/regression/filemon/Makefile
==============================================================================
--- stable/9/tools/regression/filemon/Makefile	Fri Oct 26 16:06:26 2012	(r242141)
+++ stable/9/tools/regression/filemon/Makefile	Fri Oct 26 16:07:53 2012	(r242142)
@@ -1,15 +1,33 @@
 # $FreeBSD$
 
-PROG=	filemontest
+BINS=	\
+	filemontest \
+	timed-forkb
+
+bins: filemontest timed-forkb
+all: bins
 
 NO_MAN=
 
 WARNS?=	6
 CFLAGS+= -I${.CURDIR}/../../../sys
 
+# Should be "WITHOUT_CTF=" below, but stupid infastrurture fails:
+# "/usr/share/mk/bsd.own.mk", line 489: WITH_CTF and WITHOUT_CTF can't both be set.
+WITHOUT_CDDL=
+
+CLEANFILES+=	${BINS}
+
+tests: bins
+	kldstat | grep filemon
+	${MAKE} test
+	./timed-forkb
+	@echo "filemon(4) tests passed."
+
 # Cannot use .OBJDIR -- 'filemontest' expects 'test_script.sh' in .
-test: ${PROG} clean-test
-.for BIN in ${PROG} ${PROG}32
+#FILEMONTEST32=	filemontest32
+test: filemontest clean-test
+.for BIN in filemontest ${FILEMONTEST32}
 	cd ${.CURDIR} ; \
 		for A in 1 2 3 4 5 6 7 8 9 0; do \
 		for B in 1 2 3 4 5 6 7 8 9 0; do \

Copied: stable/9/tools/regression/filemon/timed-forkb.c (from r242137, head/tools/regression/filemon/timed-forkb.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/9/tools/regression/filemon/timed-forkb.c	Fri Oct 26 16:07:53 2012	(r242142, copy of r242137, head/tools/regression/filemon/timed-forkb.c)
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2012 David O'Brien
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <err.h>
+#include <assert.h>
+
+#ifndef SLEEP
+#define	SLEEP	20	/* seconds */
+#endif
+
+int verbose;
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: %s\n", getprogname());
+	fprintf(stderr, "\t\t-n : length of fork(2) chain\n");
+	fprintf(stderr, "\t\t-t : limit run-time seconds\n");
+	exit(1);
+	/* NOTREACHED */
+}
+
+void term(int);
+void
+term(int signum)
+{
+
+	if (getpid() == getpgrp() || verbose) {
+		fprintf(stderr,
+	    "pid %d pgroup %d (ppid %d): Received SIGTERM(%d), exiting...\n",
+		    getpid(), getpgrp(), getppid(), signum);
+	 }
+	exit(1);
+}
+
+void angel_of_mercy(int);
+void
+angel_of_mercy(int sig __unused)
+{
+
+	signal(SIGALRM, SIG_IGN);	/* ignore this signal */
+	printf("Master process: alarmed waking up\n");
+	killpg(0, SIGTERM);
+	return;
+}
+
+int bombing_run(unsigned, int);
+int
+bombing_run(unsigned chainlen, int stime)
+{
+	struct rusage ru;
+	pid_t pid, cpid;
+	int status;
+
+	if (chainlen) {
+		switch (pid = fork()) {
+		case -1:
+			errx(1, "%s: can't fork", __func__);
+
+		case 0:
+			/* This is the code the child runs. */
+			bombing_run(--chainlen, stime);
+			break;
+
+		default:
+			/* This is the code the parent runs. */
+			if (getpid() == getpgrp()) {
+				signal(SIGALRM, angel_of_mercy);
+				alarm(stime);	// time for bombing run...
+				cpid = wait4(pid, &status, 0, &ru);
+				alarm(0);
+				printf(
+		"Cleanly shutting down - pid %d pgroup %d (ppid %d)\n",
+				    getpid(), getpgrp(), getppid());
+			} else {
+				cpid = wait4(pid, &status, 0, &ru);
+			}
+		}
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	time_t start /*,tvec*/;
+	char *endptr, *ctm;
+	size_t len;
+	int nflag, tflag;
+	int ch, k, maxprocperuid;
+
+	(void)signal(SIGTERM, term);
+
+	nflag = 0;
+	tflag = SLEEP;
+
+	start = time(NULL);
+	ctm = ctime(&start);
+	ctm[24] = '\0';		// see: man 3 ctime
+	fprintf(stderr, "*** fork() generation started on \"%s\" ***\n", ctm);
+
+	while ((ch = getopt(argc, argv, "n:t:v")) != -1)
+		switch (ch) {
+		case 'n':
+			nflag = strtol(optarg, &endptr, 10);
+			if (nflag <= 0 || *endptr != '\0')
+				errx(1, "illegal number, -n argument -- %s",
+				    optarg);
+			break;
+		case 't':
+			tflag = strtol(optarg, &endptr, 10);
+			if (tflag <= 0 || *endptr != '\0')
+				errx(1, "illegal number, -t argument -- %s",
+				    optarg);
+			break;
+		case 'v':
+			++verbose;
+			break;
+		default:
+			usage();
+		}
+	argv += optind;
+
+	if (!nflag) {
+		len = sizeof(maxprocperuid);
+		k = sysctlbyname("kern.maxprocperuid", &maxprocperuid, &len,
+		    NULL, 0);
+		assert(k != ENOMEM);
+		/* Try to allow a shell to still be started. */
+		nflag = maxprocperuid - 10;
+	}
+
+	// Ensure a unique process group to make killing all children easier.
+	setpgrp(0,0);
+	printf("    pid %d pgroup %d (ppid %d), %d fork chain over %d sec\n",
+	    getpid(), getpgrp(), getppid(), nflag - 1, tflag);
+
+	return bombing_run(nflag, tflag);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210261607.q9QG7raE035736>