]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix safe_fd exhaustion in fork chain caused by non closing of shared_mem_fd
authorJulian Seward <jseward@acm.org>
Wed, 15 Jun 2011 21:30:55 +0000 (21:30 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 15 Jun 2011 21:30:55 +0000 (21:30 +0000)
Patch that fixes the problem reported by Christian Borntraeger.
The problem was created by keeping the shared memory mapped file opened
without reason till the process does an exec.
In case of a chain of forked processes (without exec), the range of safe_fd
reserved for Valgrind own usage becomes exhausted.

* coregrind/m_gdbserver/remote-utils.c :
   do not VG_(safe_fd) shared_mem_fd (as it is now closed directly)
   close shared_mem_fd once file is mmap-ed and written.
* gdbserver_tests/nlfork_chain.stderr.exp,nlfork_chain.vgtest,
               fork_chain.c,nlfork_chain.stdout.exp:
     new files
* gdbserver_tests/Makefile.am:
  modified for new nlfork_chain test

(patch from #214909 c 103,
Philippe Waroquiers, philippe.waroquiers@skynet.be)

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11818

coregrind/m_gdbserver/remote-utils.c
gdbserver_tests/Makefile.am
gdbserver_tests/fork_chain.c [new file with mode: 0644]
gdbserver_tests/nlfork_chain.stderr.exp [new file with mode: 0644]
gdbserver_tests/nlfork_chain.stdout.exp [new file with mode: 0644]
gdbserver_tests/nlfork_chain.vgtest [new file with mode: 0644]

index 7797ff439c93f60714a6133cf25c8b1483b5b59d..36b891aadde6768801ea92aad0ea3b042ac2677e 100644 (file)
@@ -279,10 +279,6 @@ void remote_open (char *name)
          fatal("error writing %d bytes to shared mem %s\n",
                (int) sizeof(VgdbShared), shared_mem);
       }
-      shared_mem_fd = VG_(safe_fd)(shared_mem_fd);
-      if (shared_mem_fd == -1) {
-         fatal("safe_fd for vgdb shared_mem %s failed\n", shared_mem);
-      }
       {
          SysRes res = VG_(am_shared_mmap_file_float_valgrind)
             (sizeof(VgdbShared), VKI_PROT_READ|VKI_PROT_WRITE, 
@@ -295,6 +291,7 @@ void remote_open (char *name)
          addr_shared = sr_Res (res);
       }
       shared = (VgdbShared*) addr_shared;
+      VG_(close) (shared_mem_fd);
    }
    
    /* we open the read side FIFO in non blocking mode
index 6d9951905275a670d3df9de8e2044a3b58fc4db0..5094f5a1bb238476a9b4ae4b9ed93aff3943f9c7 100644 (file)
@@ -72,10 +72,14 @@ EXTRA_DIST = \
        nlcontrolc.stderr.exp \
        nlcontrolc.stdinB.gdb \
        nlcontrolc.stdoutB.exp \
-       nlcontrolc.vgtest
+       nlcontrolc.vgtest \
+       nlfork_chain.stderr.exp \
+       nlfork_chain.stdout.exp \
+       nlfork_chain.vgtest
 
 check_PROGRAMS = \
        clean_after_fork \
+       fork_chain \
        sleepers \
        t \
        watchpoints
diff --git a/gdbserver_tests/fork_chain.c b/gdbserver_tests/fork_chain.c
new file mode 100644 (file)
index 0000000..ae40f6e
--- /dev/null
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+void fork_chain(int level)
+{
+   int pid;
+
+   printf ("forking level %d\n", level);
+   fflush (stdout);
+   pid = fork();
+   if (pid == -1) {
+      perror("fork");
+      exit(1);
+   }
+
+   if (pid == 0) {
+      if (level > 0) {
+         fork_chain (level - 1);
+      }
+   } else {
+      int ret;
+      int status;
+      while((ret = waitpid(pid, &status, 0)) != pid) {
+         if (errno != EINTR) {
+            perror("waitpid");
+            exit(1);
+         }
+      }
+   }
+}
+int main()
+{
+   fork_chain (20);
+   return 0;
+}
diff --git a/gdbserver_tests/nlfork_chain.stderr.exp b/gdbserver_tests/nlfork_chain.stderr.exp
new file mode 100644 (file)
index 0000000..a0eeaba
--- /dev/null
@@ -0,0 +1,24 @@
+Nulgrind, the minimal Valgrind tool
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gdbserver_tests/nlfork_chain.stdout.exp b/gdbserver_tests/nlfork_chain.stdout.exp
new file mode 100644 (file)
index 0000000..a263b7e
--- /dev/null
@@ -0,0 +1,21 @@
+forking level 20
+forking level 19
+forking level 18
+forking level 17
+forking level 16
+forking level 15
+forking level 14
+forking level 13
+forking level 12
+forking level 11
+forking level 10
+forking level 9
+forking level 8
+forking level 7
+forking level 6
+forking level 5
+forking level 4
+forking level 3
+forking level 2
+forking level 1
+forking level 0
diff --git a/gdbserver_tests/nlfork_chain.vgtest b/gdbserver_tests/nlfork_chain.vgtest
new file mode 100644 (file)
index 0000000..fda4bc3
--- /dev/null
@@ -0,0 +1,4 @@
+# test that gdbserver properly cleans up its resources in a chain
+# of forked processes.
+prog: fork_chain
+vgopts: --tool=none --vgdb=yes --trace-children=yes --vgdb-prefix=./vgdb-prefix-nlfork_chain