From b8c87dee815d9d20b65fe97e6f838c6937cdf6ab Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Wed, 3 Apr 2013 10:55:00 +0200 Subject: Show backtraces for core files from CppunitTests, too Change-Id: Idff2831913b6fb6e5b522ae36fffeb345e3a1140 --- solenv/bin/gdb-core-bt.sh | 61 ++++++++++++++++++ solenv/gbuild/CppunitTest.mk | 10 ++- solenv/gbuild/UnoApiTarget.mk | 3 +- solenv/gbuild/platform/solaris.mk | 6 +- solenv/gbuild/platform/unxgcc.mk | 6 +- solenv/gbuild/platform/unxgcc_gdbforjunit.sh | 66 ------------------- .../java/org/openoffice/test/OfficeConnection.java | 73 +++++++++++++--------- 7 files changed, 125 insertions(+), 100 deletions(-) create mode 100755 solenv/bin/gdb-core-bt.sh delete mode 100755 solenv/gbuild/platform/unxgcc_gdbforjunit.sh diff --git a/solenv/bin/gdb-core-bt.sh b/solenv/bin/gdb-core-bt.sh new file mode 100755 index 000000000000..4cbcf52a54b4 --- /dev/null +++ b/solenv/bin/gdb-core-bt.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License or as specified alternatively below. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Bjoern Michaelsen +# Portions created by the Initial Developer are Copyright (C) 2010 Canonical, +# Ltd. . All Rights Reserved. +# +# Major Contributor(s): +# +# For minor contributions see the git repository. +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +# + +EXECUTABLE=${1} +COREDIR=${2} + +if test -n "$(which gdb)" +then + if test "$(ls "$COREDIR"/core* 2>/dev/null | wc -l)" -eq 1 + then + COREFILE=$(ls "$COREDIR"/core*) + echo + echo "It looks like ${EXECUTABLE} generated a core file at ${COREFILE}" + echo "Backtraces:" + GDBCOMMANDFILE=`mktemp` + echo "thread apply all backtrace" > "$GDBCOMMANDFILE" + gdb -x "$GDBCOMMANDFILE" --batch "$EXECUTABLE" "$COREFILE" + rm "$GDBCOMMANDFILE" + echo + exit 0 + else + echo + echo "No core file identified in directory ${COREDIR}" + echo "To show backtraces for crashes during test execution," + echo "enable core files with:" + echo + echo " ulimit -c unlimited" + echo + exit 1 + fi +else + echo "You need gdb in your path to show backtraces" + exit 1 +fi diff --git a/solenv/gbuild/CppunitTest.mk b/solenv/gbuild/CppunitTest.mk index 8e809d021b00..e9669b010f4c 100644 --- a/solenv/gbuild/CppunitTest.mk +++ b/solenv/gbuild/CppunitTest.mk @@ -83,6 +83,9 @@ $(call gb_CppunitTest_get_target,%) :| $(gb_CppunitTest_CPPTESTDEPS) $(call gb_Output_announce,$*,$(true),CUT,2) $(call gb_Helper_abbreviate_dirs,\ mkdir -p $(dir $@) && \ + $(if $(gb_CppunitTest__interactive),, \ + $(if $(value gb_CppunitTest_postprocess), \ + rm -fr $@.core && mkdir $@.core && cd $@.core &&)) \ ($(gb_CppunitTest_CPPTESTPRECOMMAND) \ $(if $(G_SLICE),G_SLICE=$(G_SLICE)) \ $(if $(GLIBCXX_FORCE_NEW),GLIBCXX_FORCE_NEW=$(GLIBCXX_FORCE_NEW)) \ @@ -92,7 +95,12 @@ $(call gb_CppunitTest_get_target,%) :| $(gb_CppunitTest_CPPTESTDEPS) $(ICECREAM_RUN) $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_CPPTESTCOMMAND) \ $(call gb_LinkTarget_get_target,CppunitTest/$(call gb_CppunitTest_get_libfilename,$*)) \ $(call gb_CppunitTest__make_args) \ - $(if $(gb_CppunitTest__interactive),,> $@.log 2>&1 || (cat $@.log && $(UNIT_FAILED_MSG) && false)))) + $(if $(gb_CppunitTest__interactive),, \ + > $@.log 2>&1 \ + || (cat $@.log && $(UNIT_FAILED_MSG) \ + $(if $(value gb_CppunitTest_postprocess), \ + && $(call gb_CppunitTest_postprocess,$(gb_CppunitTest_CPPTESTCOMMAND),$@.core)) \ + && false)))) define gb_CppunitTest_CppunitTest $(call gb_CppunitTest__CppunitTest_impl,$(1),$(call gb_CppunitTest__get_linktargetname,$(1))) diff --git a/solenv/gbuild/UnoApiTarget.mk b/solenv/gbuild/UnoApiTarget.mk index 35e7c1836ee3..63807b8d4c8d 100644 --- a/solenv/gbuild/UnoApiTarget.mk +++ b/solenv/gbuild/UnoApiTarget.mk @@ -303,8 +303,7 @@ define gb_UnoApiHeadersTarget__command RESPONSEFILE=$(call var2file,$(shell $(gb_MKTEMP)),100,\ $(UNOAPI_DEPS)) && \ $(gb_UnoApiHeadersTarget_CPPUMAKERCOMMAND) \ - -Gc $(4) -BUCR \ - -O$(3) $(call gb_UnoApiTarget_get_target,$(2)) \ + -Gc $(4) -O$(3) $(call gb_UnoApiTarget_get_target,$(2)) \ @$${RESPONSEFILE} && \ rm -f $${RESPONSEFILE} && \ touch $(1) diff --git a/solenv/gbuild/platform/solaris.mk b/solenv/gbuild/platform/solaris.mk index 1cc130cb27cd..7f6c71b28b4c 100644 --- a/solenv/gbuild/platform/solaris.mk +++ b/solenv/gbuild/platform/solaris.mk @@ -333,6 +333,10 @@ $(call gb_LinkTarget_get_target,$(2)) : RPATH := endef +define gb_CppunitTest_postprocess +$(SRCDIR)/solenv/bin/gdb-core-bt.sh $(1) $(2) +endef + # JunitTest class ifneq ($(OOO_TEST_SOFFICE),) @@ -350,7 +354,7 @@ $(call gb_JunitTest_get_target,$(1)) : DEFS := \ -Dorg.openoffice.test.arg.env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ -Dorg.openoffice.test.arg.user=$(call gb_Helper_make_url,$(call gb_JunitTest_get_userdir,$(1))) \ -Dorg.openoffice.test.arg.workdir=$(call gb_JunitTest_get_userdir,$(1)) \ - -Dorg.openoffice.test.arg.postprocesscommand=$(GBUILDDIR)/platform/unxgcc_gdbforjunit.sh \ + -Dorg.openoffice.test.arg.postprocesscommand=$(SRCDIR)/solenv/bin/gdb-core-bt.sh \ -Dorg.openoffice.test.arg.soffice="$(gb_JunitTest_SOFFICEARG)" \ endef diff --git a/solenv/gbuild/platform/unxgcc.mk b/solenv/gbuild/platform/unxgcc.mk index 0a356898e8d6..630d0c4ec932 100644 --- a/solenv/gbuild/platform/unxgcc.mk +++ b/solenv/gbuild/platform/unxgcc.mk @@ -329,6 +329,10 @@ $(call gb_LinkTarget_get_target,$(2)) : RPATH := endef +define gb_CppunitTest_postprocess +$(SRCDIR)/solenv/bin/gdb-core-bt.sh $(1) $(2) +endef + # JunitTest class ifneq ($(OOO_TEST_SOFFICE),) @@ -346,7 +350,7 @@ $(call gb_JunitTest_get_target,$(1)) : DEFS := \ -Dorg.openoffice.test.arg.env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ -Dorg.openoffice.test.arg.user=$(call gb_Helper_make_url,$(call gb_JunitTest_get_userdir,$(1))) \ -Dorg.openoffice.test.arg.workdir=$(call gb_JunitTest_get_userdir,$(1)) \ - -Dorg.openoffice.test.arg.postprocesscommand=$(GBUILDDIR)/platform/unxgcc_gdbforjunit.sh \ + -Dorg.openoffice.test.arg.postprocesscommand=$(SRCDIR)/solenv/bin/gdb-core-bt.sh \ -Dorg.openoffice.test.arg.soffice="$(gb_JunitTest_SOFFICEARG)" \ endef diff --git a/solenv/gbuild/platform/unxgcc_gdbforjunit.sh b/solenv/gbuild/platform/unxgcc_gdbforjunit.sh deleted file mode 100755 index 0341e7b7a592..000000000000 --- a/solenv/gbuild/platform/unxgcc_gdbforjunit.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# -# Version: MPL 1.1 / GPLv3+ / LGPLv3+ -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License or as specified alternatively below. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Initial Developer of the Original Code is -# Bjoern Michaelsen -# Portions created by the Initial Developer are Copyright (C) 2010 Canonical, -# Ltd. . All Rights Reserved. -# -# Major Contributor(s): -# -# For minor contributions see the git repository. -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 3 or later (the "GPLv3+"), or -# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), -# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable -# instead of those above. -# - -# we expect our work directory to be where soffice had been started -# $(1) should be the path to the executable - -OFFICEFILE=${1} -WORKDIR=${2} - -if test -n "`which gdb`" -then - if test `ls "${WORKDIR}"/core* 2>/dev/null | wc -l` -eq 1 - then - COREFILE=`ls "${WORKDIR}"/core*` - echo - echo "It seems like soffice.bin crashed during the test excution!" - echo "Found a core dump at ${COREFILE}" - echo "Stacktrace:" - GDBCOMMANDFILE=`mktemp` - echo "thread apply all bt" > ${GDBCOMMANDFILE} - gdb -x $GDBCOMMANDFILE --batch ${OFFICEFILE}.bin ${COREFILE} - rm ${GDBCOMMANDFILE} - echo - exit 1 - else - echo - echo "No core dump at ${WORKDIR}, to create core dumps (and stack traces)" - echo "for crashed soffice instances, enable core dumps with:" - echo - echo " ulimit -c unlimited" - echo - exit 0 - fi -else - echo "You need gdb in your path to generate stacktraces." - exit 0 -fi - -# vim: set et sw=4 sts=4: diff --git a/unotest/source/java/org/openoffice/test/OfficeConnection.java b/unotest/source/java/org/openoffice/test/OfficeConnection.java index d8774a1958c7..de6e7054ff4b 100644 --- a/unotest/source/java/org/openoffice/test/OfficeConnection.java +++ b/unotest/source/java/org/openoffice/test/OfficeConnection.java @@ -43,11 +43,6 @@ import static org.junit.Assert.*; public final class OfficeConnection { - private final class PostprocessFailedException extends java.lang.RuntimeException { - PostprocessFailedException() { - super("This likely means that soffice crashed during the test."); - } - }; /** Start up an OOo instance. */ public void setUp() throws Exception { @@ -108,6 +103,7 @@ public final class OfficeConnection { public void tearDown() throws InterruptedException, com.sun.star.uno.Exception { + boolean cleanTermination = false; try { boolean desktopTerminated = true; if (process != null) { @@ -148,38 +144,45 @@ public final class OfficeConnection { if (process != null) { code = process.waitFor(); } - boolean outTerminated = outForward == null || outForward.terminated(); - boolean errTerminated = errForward == null || errForward.terminated(); + boolean outTerminated = outForward == null + || outForward.terminated(); + boolean errTerminated = errForward == null + || errForward.terminated(); assertEquals(0, code); + cleanTermination = true; assertTrue(outTerminated); assertTrue(errTerminated); } finally { - try { - String sofficeArg = Argument.get("soffice"); - String workdir = Argument.get("workdir"); - String postprocesscommand = Argument.get("postprocesscommand"); - if(sofficeArg.startsWith("path:") && workdir != null && postprocesscommand != null) { - ProcessBuilder pb = new ProcessBuilder( - postprocesscommand, - sofficeArg.substring("path:".length()), - workdir); - Process postprocess = pb.start(); - Forward ppoutForward = new Forward(postprocess.getInputStream(), System.out); - ppoutForward.start(); - Forward pperrForward = new Forward(postprocess.getErrorStream(), System.err); - pperrForward.start(); - postprocess.waitFor(); - if(postprocess.exitValue() != 0) + if (!cleanTermination) { + try { + String sofficeArg = Argument.get("soffice"); + String workdir = Argument.get("workdir"); + String postprocesscommand = Argument.get( + "postprocesscommand"); + if (sofficeArg.startsWith("path:") && workdir != null + && postprocesscommand != null) { - // no ugly long java stacktrace needed here - PostprocessFailedException e = new PostprocessFailedException(); - StackTraceElement[] newStackTrace = new StackTraceElement[0]; - e.setStackTrace(newStackTrace); - throw e; + ProcessBuilder pb = new ProcessBuilder( + postprocesscommand, + sofficeArg.substring("path:".length()) + ".bin", + workdir); + Process postprocess = pb.start(); + Forward ppoutForward = new Forward( + postprocess.getInputStream(), System.out); + ppoutForward.start(); + Forward pperrForward = new Forward( + postprocess.getErrorStream(), System.err); + pperrForward.start(); + int code = postprocess.waitFor(); + if (code != 0) { + throw new PostprocessFailedException(code); + } } } + catch (IOException e) { + throw new PostprocessFailedException(e); + } } - catch(IOException e) {} } } @@ -262,6 +265,18 @@ public final class OfficeConnection { private boolean done = false; } + private static final class PostprocessFailedException + extends RuntimeException + { + PostprocessFailedException(int exitCode) { + super("postprocessing failed with exit code " + exitCode); + } + + PostprocessFailedException(IOException cause) { + super("postprocessing failed with IOException " + cause, cause); + } + }; + private String description; private Process process = null; private Forward outForward = null; -- cgit