[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH 2/2] lib: Add comment and regression test for case where main process has large heap.



Thanks: Dan Berrangé for identifying the problem.
---
 .gitignore                        |  1 +
 src/command.c                     | 11 +++++++
 tests/regressions/Makefile.am     | 13 +++++++-
 tests/regressions/test-big-heap.c | 69 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 tests/regressions/test-big-heap.c

diff --git a/.gitignore b/.gitignore
index cb5bc49..2f571a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -582,6 +582,7 @@ Makefile.in
 /tests/regressions/rhbz914931
 /tests/regressions/rhbz1044014.out
 /tests/regressions/rhbz1055452
+/tests/regressions/test-big-heap
 /tests/rsync/rsyncd.pid
 /tests/syslinux/extlinux-guest.img
 /tests/syslinux/syslinux-guest.img
diff --git a/src/command.c b/src/command.c
index 0547111..e9f357a 100644
--- a/src/command.c
+++ b/src/command.c
@@ -558,6 +558,17 @@ run_child (struct command *cmd)
   }
 #endif /* HAVE_SETRLIMIT */
 
+  /* NB: If the main process (which we have forked a copy of) uses
+   * more heap than the RLIMIT_AS we set above, then any call to
+   * malloc or any extension of the stack will fail with ENOMEM or
+   * SIGSEGV respectively.  Luckily we only use RLIMIT_AS followed by
+   * execvp below, so we get away with it, but adding any code here
+   * could cause a failure.
+   *
+   * There is a regression test for this.  See:
+   * tests/regressions/test-big-heap.c
+   */
+
   /* Run the command. */
   switch (cmd->style) {
   case COMMAND_STYLE_EXECV:
diff --git a/tests/regressions/Makefile.am b/tests/regressions/Makefile.am
index 74f23dd..c4f60ae 100644
--- a/tests/regressions/Makefile.am
+++ b/tests/regressions/Makefile.am
@@ -71,6 +71,7 @@ TESTS = \
 	rhbz1091803.sh \
 	rhbz1175196.sh \
 	rhbz1232192.sh \
+	test-big-heap \
 	test-noexec-stack.pl
 
 if HAVE_LIBVIRT
@@ -89,7 +90,8 @@ check_PROGRAMS = \
 	rhbz501893 \
 	rhbz790721 \
 	rhbz914931 \
-	rhbz1055452
+	rhbz1055452 \
+	test-big-heap
 
 rhbz501893_SOURCES = rhbz501893.c
 rhbz501893_CPPFLAGS = \
@@ -130,5 +132,14 @@ rhbz1055452_CFLAGS = \
 rhbz1055452_LDADD = \
 	$(top_builddir)/src/libguestfs.la
 
+test_big_heap_SOURCES = test-big-heap.c
+test_big_heap_CPPFLAGS = \
+	-I$(top_srcdir)/src -I$(top_builddir)/src \
+	-DGUESTFS_PRIVATE=1
+test_big_heap_CFLAGS = \
+	$(WARN_CFLAGS) $(WERROR_CFLAGS)
+test_big_heap_LDADD = \
+	$(top_builddir)/src/libguestfs.la
+
 check-slow:
 	$(MAKE) TESTS="rhbz909624.sh" check
diff --git a/tests/regressions/test-big-heap.c b/tests/regressions/test-big-heap.c
new file mode 100644
index 0000000..ddce270
--- /dev/null
+++ b/tests/regressions/test-big-heap.c
@@ -0,0 +1,69 @@
+/* libguestfs
+ * Copyright (C) 2015 Red Hat Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/* Test that allocating lots of heap in the main program doesn't cause
+ * libguestfs to fail when it runs qemu-img.  When we call qemu-img,
+ * after forking but before execing, we set RLIMIT_AS to 1 GB.  If the
+ * main program is using more than 1 GB, then any malloc or stack
+ * extension will fail.  We get away with this by calling exec
+ * immediately after setting the rlimit, but it only just works, and
+ * this test is designed to catch any regressions.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+
+int
+main (int argc, char *argv[])
+{
+  guestfs_h *g = guestfs_create ();
+  char *mem, *fmt;
+
+  /* Make sure we're using > 1GB in the main process. */
+  mem = calloc (2 * 1024, 1024 * 1024);
+  assert (mem != NULL);
+
+  /* Do something which forks qemu-img subprocess. */
+  fmt = guestfs_disk_format (g, "/dev/null");
+  if (fmt == NULL) {
+    /* Test failed. */
+    fprintf (stderr, "%s: unexpected failure of test, see earlier messages\n",
+             argv[0]);
+    exit (EXIT_FAILURE);
+  }
+
+  if (STRNEQ (fmt, "raw")) {
+    /* Test failed. */
+    fprintf (stderr, "%s: unexpected output: expected 'raw' actual '%s'\n",
+             argv[0], fmt);
+    exit (EXIT_FAILURE);
+  }
+
+  /* Test successful. */
+
+  free (fmt);
+  free (mem);
+  exit (EXIT_SUCCESS);
+}
-- 
2.5.0


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]