This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH,boehm-gc,PR42811] Add followup testcase to
- From: Dave Korn <dave dot korn dot cygwin at googlemail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Java Patches <java-patches at gcc dot gnu dot org>
- Date: Tue, 27 Apr 2010 04:49:28 +0100
- Subject: [PATCH,boehm-gc,PR42811] Add followup testcase to
Hello again,
One issue that was exposed(*) when I fixed GCC PR42811(**) was that when you
have a shared library that proxies access to the GC, as indeed libjava
effectively does, and in particular when is is from within that shared library
that the GC is initialised, it may end up being that it is only the library's
data and bss sections that get registered to be scanned for static roots, and
that the GC may lose sight of pointers to GC-allocated memory if the library
returns them to the main application, which hangs onto a copy of the pointer
in its own data or bss space while the library does not.
This doesn't in fact arise on Linux platforms, where there is dynamic
registration of loaded modules, but it used to happen on Windows before I
fixed it. I said I'd look at following up with a testcase, and here it is.
The attached testcase simulates the interaction between shared libjava
containing statically-linked GC and an application as described above. On
i686-pc-cygwin, it reliably failed prior to the patch for PR42811, and
reliably passes since then; on i686-pc-linux-gnu, it passes in either case anyway.
While I was at it, I noticed that we've disabled all but one of the boehm-gc
tests in our copy of the tree. Being as I was in there anyway, I decided to
see what happened if I re-enabled a couple of the others; they all passed on
both cygwin and linux targets, so I thought, "Why not?"(***), and left them there.
boehm-gc/ChangeLog:
* tests/staticrootstest.c: New test source file.
* boehm-gc/tests/staticrootslib.c: New test library source file.
* Makefile.am (test_ldadd): New variable.
(gctest_LDADD): Use it.
(TESTS): Add leaktest, middletest and staticrootstest.
(check_PROGRAMS): Likewise.
(leaktest_SOURCES): New libtool variable definition.
(leaktest_LDADD): Likewise.
(leaktest_LDFLAGS): Likewise.
(leaktest_LINK): Likewise.
(middletest_SOURCES): Likewise.
(middletest_LDADD): Likewise.
(middletest_LDFLAGS): Likewise.
(middletest_LINK): Likewise.
(staticrootstest_SOURCES): Likewise.
(staticrootstest_LDADD): Likewise.
(staticrootstest_LDFLAGS): Likewise.
(staticrootstest_LINK): Likewise.
(check_LTLIBRARIES): Likewise.
(libstaticrootslib_la_SOURCES): Likewise.
(libstaticrootslib_la_LIBADD): Likewise.
(libstaticrootslib_la_LDFLAGS): Likewise.
(libstaticrootslib_la_DEPENDENCIES): Likewise.
The new test has already been committed upstream. I just re-verified that
all the tests pass on i686-pc-cygwin from my latest LTO build from earlier
last night. OK for HEAD?
cheers,
DaveK
--
(*) - http://gcc.gnu.org/ml/java/2010-02/threads.html#00004
(**) - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42811
(***) - That's a good reason for almost anything - a bit used perhaps, but
still quite serviceable.
Index: boehm-gc/tests/staticrootstest.c
===================================================================
--- boehm-gc/tests/staticrootstest.c (revision 0)
+++ boehm-gc/tests/staticrootstest.c (revision 0)
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+#ifndef GC_DEBUG
+# define GC_DEBUG
+#endif
+
+#include "gc.h"
+#include "gc_backptr.h"
+
+struct treenode {
+ struct treenode *x;
+ struct treenode *y;
+} * root[10];
+
+static char *staticroot = 0;
+
+extern struct treenode * libsrl_mktree(int i);
+extern void * libsrl_init(void);
+extern void * libsrl_collect (void);
+
+int main(void)
+{
+ int i;
+ staticroot = libsrl_init();
+ for (i = 0; i < sizeof(struct treenode); ++i) {
+ staticroot[i] = 0x42;
+ }
+ libsrl_collect();
+ for (i = 0; i < 10; ++i) {
+ root[i] = libsrl_mktree(12);
+ libsrl_collect();
+ }
+ for (i = 0; i < sizeof(struct treenode); ++i) {
+ if (staticroot[i] != 0x42)
+ return -1;
+ }
+ for (i = 0; i < 10; ++i) {
+ root[i] = libsrl_mktree(12);
+ libsrl_collect();
+ }
+ for (i = 0; i < sizeof(struct treenode); ++i) {
+ if (staticroot[i] != 0x42)
+ return -1;
+ }
+ return 0;
+}
Index: boehm-gc/tests/staticrootslib.c
===================================================================
--- boehm-gc/tests/staticrootslib.c (revision 0)
+++ boehm-gc/tests/staticrootslib.c (revision 0)
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+#ifndef GC_DEBUG
+# define GC_DEBUG
+#endif
+
+#include "gc.h"
+
+struct treenode {
+ struct treenode *x;
+ struct treenode *y;
+} * root[10];
+
+struct treenode * libsrl_mktree(int i)
+{
+ struct treenode * r = GC_MALLOC(sizeof(struct treenode));
+ if (0 == i) return 0;
+ if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode));
+ r -> x = libsrl_mktree(i-1);
+ r -> y = libsrl_mktree(i-1);
+ return r;
+}
+
+void * libsrl_init(void)
+{
+ GC_INIT();
+ return GC_MALLOC(sizeof(struct treenode));
+}
+
+void * libsrl_collect (void)
+{
+ GC_gcollect();
+}
Index: boehm-gc/Makefile.am
===================================================================
--- boehm-gc/Makefile.am (revision 158764)
+++ boehm-gc/Makefile.am (working copy)
@@ -48,14 +48,43 @@ libgcjgc_convenience_la_DEPENDENCIES = @addobjs@
AM_CXXFLAGS = @GC_CFLAGS@
AM_CFLAGS = @GC_CFLAGS@
+test_ldadd = libgcjgc.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
+
check_PROGRAMS = gctest
gctest_SOURCES = tests/test.c
-gctest_LDADD = libgcjgc.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
+gctest_LDADD = $(test_ldadd)
gctest_LDFLAGS = -shared-libgcc
gctest_LINK = $(LINK) $(gctest_LDFLAGS)
TESTS_ENVIRONMENT = LD_LIBRARY_PATH=../../$(MULTIBUILDTOP)gcc
TESTS = gctest
+TESTS += leaktest$(EXEEXT)
+check_PROGRAMS += leaktest
+leaktest_SOURCES = tests/leak_test.c
+leaktest_LDADD = $(test_ldadd)
+leaktest_LDFLAGS = -shared-libgcc
+leaktest_LINK = $(LINK) $(leaktest_LDFLAGS)
+
+TESTS += middletest$(EXEEXT)
+check_PROGRAMS += middletest
+middletest_SOURCES = tests/middle.c
+middletest_LDADD = $(test_ldadd)
+middletest_LDFLAGS = -shared-libgcc
+middletest_LINK = $(LINK) $(middletest_LDFLAGS)
+
+TESTS += staticrootstest$(EXEEXT)
+check_PROGRAMS += staticrootstest
+staticrootstest_SOURCES = tests/staticrootstest.c
+staticrootstest_LDADD = $(test_ldadd) libstaticrootslib.la
+staticrootstest_LDFLAGS = -shared-libgcc
+staticrootstest_LINK = $(LINK) $(staticrootstest_LDFLAGS)
+check_LTLIBRARIES = libstaticrootslib.la
+libstaticrootslib_la_SOURCES = tests/staticrootslib.c
+libstaticrootslib_la_LIBADD = libgcjgc_convenience.la
+libstaticrootslib_la_LDFLAGS = -version-info 1:2:0 -no-undefined \
+ -rpath /nowhere -shared-libgcc
+libstaticrootslib_la_DEPENDENCIES = libgcjgc_convenience.la
+
## FIXME: we shouldn't have to do this, but automake forces us to.
.s.lo:
## We use -Wp,-P to strip #line directives. Irix `as' chokes on