syscalls/pipe07: Rewrite.
* Remove useless comments & usuall stuff.
* Get rid of the ugly system() and use readdir()
to count number of open files.
(and remove the ugly hacks to create temp dirs
that are no longer needed)
* Close the pipes after the test has finished
so that test looping works
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/testcases/kernel/syscalls/pipe/pipe07.c b/testcases/kernel/syscalls/pipe/pipe07.c
index c774870..7e3b914 100644
--- a/testcases/kernel/syscalls/pipe/pipe07.c
+++ b/testcases/kernel/syscalls/pipe/pipe07.c
@@ -1,112 +1,81 @@
/*
+ * Copyright (c) International Business Machines Corp., 2002
+ * Ported by Paul Larson
+ * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
*
- * Copyright (c) International Business Machines Corp., 2002
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
- * NAME
- * pipe07.c
- *
- * DESCRIPTION
- * Test the ability of pipe to open the maximum even number of file
- * descriptors permitted (or (maxfds - 3)/2 pipes)
+ * Test the ability of pipe to open the maximum even number of file
+ * descriptors permitted (or (maxfds - 3)/2 pipes)
*
* ALGORITHM
- * 1. open pipes until EMFILE is returned
- * 2. check to see that the number of pipes opened is
- * (maxfds - 3) / 2
- *
- * USAGE: <for command-line>
- * pipe07 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * HISTORY
- * 12/2002 Ported by Paul Larson
- *
- * RESTRICTIONS
- * None
+ * 1. record file descriptors open prior to test run
+ * 2. open pipes until EMFILE is returned
+ * 3. check to see that the number of pipes opened is (maxfds - 3) / 2
+ * 4. close all fds in range 0, maximal fd that were not open prior to
+ * the test execution
*/
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
#include "test.h"
#include "usctest.h"
+#include "safe_macros.h"
char *TCID = "pipe07";
int TST_TOTAL = 1;
-int exp_enos[] = { EMFILE, 0 };
+static int exp_enos[] = { EMFILE, 0 };
-int pipe_ret, pipes[2];
-char currdir[PATH_MAX];
-char *tempdir = NULL;
-void setup(void);
-void cleanup(void);
+/* used to record file descriptors open at the test start */
+static int rec_fds[128];
+static int rec_fds_max;
+static void record_open_fds(void);
+static void close_test_fds(int max_fd);
+
+static void setup(void);
+static void cleanup(void);
int main(int ac, char **av)
{
int lc;
char *msg;
- int min; /* number of file descriptors */
- int usedfds; /* number of currently used file descriptors */
- int npipes; /* number of pipes opened */
- pid_t mypid; /* process of id of test */
- char *cmdstring = NULL; /* hold command string to execute using system() */
- FILE *f; /* used for retrieving the used fds */
+ int min, ret;
+ int npipes;
+ int pipes[2], max_fd = 0;
if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
- setup();
- /* Get the currently used number of file descriptors */
- mypid = getpid();
- cmdstring = malloc(BUFSIZ);
- snprintf(cmdstring, BUFSIZ, "test -d /proc/%d/fd || exit 1 ; "
- "ls -A -1 /proc/%d/fd | wc -l | awk {'print $1'} > pipe07.tmp",
- mypid, mypid);
- if (system(cmdstring) == 0) {
- f = fopen("pipe07.tmp", "r");
- fscanf(f, "%d", &usedfds);
- fclose(f);
- } else
- usedfds = 3; /* Could not get processes used fds, so assume 3 */
- unlink("pipe07.tmp");
- TEST_EXP_ENOS(exp_enos);
+ setup();
+
+ min = getdtablesize() - rec_fds_max;
for (lc = 0; TEST_LOOPING(lc); lc++) {
-
- /* reset tst_count in case we are looping */
tst_count = 0;
- min = getdtablesize();
-
- /* subtract used fds */
- min -= usedfds;
-
for (npipes = 0;; npipes++) {
- pipe_ret = pipe(pipes);
- if (pipe_ret < 0) {
+ ret = pipe(pipes);
+ if (ret < 0) {
if (errno != EMFILE) {
tst_brkm(TFAIL, cleanup,
"got unexpected error - %d",
@@ -114,59 +83,101 @@
}
break;
}
+
+ max_fd = MAX(pipes[0], max_fd);
+ max_fd = MAX(pipes[1], max_fd);
}
+
if (npipes == (min / 2))
tst_resm(TPASS, "Opened %d pipes", npipes);
else
tst_resm(TFAIL, "Unable to open maxfds/2 pipes");
+ close_test_fds(max_fd);
+ max_fd = 0;
}
+
cleanup();
tst_exit();
-
}
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup()
+static void setup(void)
{
- char template[PATH_MAX];
-
- /* I had to do this, instead of tst_tmpdir() b/c I was receiving *
- * a SIGSEGV for some reason when I tried to use tst_tmpdir/tst_rmdir */
-
- /* Save current working directory */
- getcwd(currdir, PATH_MAX);
-
- /* Create temp directory and cd to it */
- snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID);
- tempdir = mkdtemp(template);
- chdir(tempdir);
-
+ TEST_EXP_ENOS(exp_enos);
tst_sig(FORK, DEF_HANDLER, cleanup);
-
TEST_PAUSE;
+ record_open_fds();
}
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- * completion or premature exit.
- */
-void cleanup()
+static void record_open_fds(void)
{
- /*
- * print timing stats if that option was specified.
- * print errno log if that option was specified.
- */
+ DIR *dir = opendir("/proc/self/fd");
+ int dir_fd, fd;
+ struct dirent *file;
+
+ if (dir == NULL)
+ tst_brkm(TBROK | TERRNO, cleanup, "opendir()");
+
+ dir_fd = dirfd(dir);
+
+ if (dir_fd == -1)
+ tst_brkm(TBROK | TERRNO, cleanup, "dirfd()");
+
+ errno = 0;
+
+ while ((file = readdir(dir))) {
+ if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
+ continue;
+
+ fd = atoi(file->d_name);
+
+ if (fd == dir_fd)
+ continue;
+
+ if (rec_fds_max >= ARRAY_SIZE(rec_fds)) {
+ tst_brkm(TBROK, cleanup,
+ "Too much file descriptors open");
+ }
+
+ rec_fds[rec_fds_max++] = fd;
+ }
+
+ if (errno)
+ tst_brkm(TBROK | TERRNO, cleanup, "readdir()");
+
+ closedir(dir);
+
+ tst_resm(TINFO, "Found %u files open", rec_fds_max);
+}
+
+static int not_recorded(int fd)
+{
+ int i;
+
+ for (i = 0; i < rec_fds_max; i++)
+ if (fd == rec_fds[i])
+ return 0;
+
+ return 1;
+}
+
+static void close_test_fds(int max_fd)
+{
+ int i;
+
+ for (i = 0; i <= max_fd; i++) {
+ if (not_recorded(i)) {
+ if (close(i)) {
+ if (errno == EBADF)
+ continue;
+ tst_resm(TWARN | TERRNO, "close(%i)", i);
+ }
+ }
+ }
+}
+
+static void cleanup(void)
+{
TEST_CLEANUP;
-
- /* I had to do this, instead of tst_tmpdir() b/c I was receiving *
- * a SIGSEGV for some reason when I tried to use tst_tmpdir/tst_rmdir */
-
- /* Chdir back to original working directory */
- chdir(currdir);
-
- rmdir(tempdir);
}