This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: [gcov] No data gathered for child processes
- From: Scott Spivak <scott dot spivak at hp dot com>
- To: gcc-help at gcc dot gnu dot org
- Date: Tue, 12 Aug 2014 20:10:12 +0000 (UTC)
- Subject: Re: [gcov] No data gathered for child processes
- Authentication-results: sourceware.org; auth=none
- References: <4AB52B56 dot 60303 at free dot fr> <20090921222132 dot GA4217 at koretsu> <4ABA4C43 dot 9080700 at free dot fr>
Didier 'Ptitjes' <ptitjes <at> free.fr> writes:
>
> Hi Holger,
>
> First thanks for your support.
>
> Holger Blasum wrote:
> > Hello Didier,
> >
> > On Sat, Sep 19, 2009 at 09:04:54PM +0200, Didier Ptitjes wrote:
> >> GTest forks the test process in order to test for asserting tests.
> >> Looking at the reports of lcov, it looks like there is absolutely no
> >> information gathered about the child processes.
> > ...
> >> I already have seen this question asked two times on gcc-help but none
> >> got a real answer:
> >> http://gcc.gnu.org/ml/gcc-help/2009-07/msg00334.html
> >> http://gcc.gnu.org/ml/gcc/2008-09/msg00490.html
> >
> > Hmm, I have no quick idea how to fix your problem, but it might be
> > helpful to understand where it occurs (then one can think of a
> > work-around): basically the gcov tools work in a way
> > (1) that enabling -ftest-coverage will result in a different binary
> > than the binary without -ftest-coverage (1.4.1 in [1]), this gives you
> > *.gcno files
> > (2) when the instrumented binary it is run you have a data
> > collection (1.4.2 in [1]) phase where the binary adds up
> > counters in memory whenever passing through C sequence points
> > and then you have a reporting phase where the memory data is dumped
> > into *.gcda files.
> > (3) then there is a reporting phase (1.4.3 in [1]) where that *.gcda
> > and *.gcno files are converted into *.gcov files
> >
> > The first thing to divide and conquer this would be to test and report
> > * whether after the phase (1) all *.gcno files are built for both
> > parent and child,
> > * whether after the phase (2) all *.gcda files are built/modified
> > for parent and child.
>
> OK, I can confirm that I actually have *.gcno and *.gcda files for every
> of my library .c files. (I tried to build them for test cases themselves
> without any change).
>
> You must note that the parent process and the child processes have the
> exact same code. In fact, the parent process is just forked.
>
> For an example of the forking code you can look at:
>
http://git.gnome.org/cgit/libgee/tree/tests/testreadonlycollection.vala#n121
>
> This is Vala code but it is just transformed into the following C code:
>
> <code>
> if (g_test_trap_fork ((guint64) 0, G_TEST_TRAP_SILENCE_STDOUT |
> G_TEST_TRAP_SILENCE_STDERR)) {
> g_assert (gee_collection_add (self->ro_collection, "two"));
> _g_object_unref0 (dummy);
> return;
> }
> g_test_trap_assert_failed ();
> g_assert (gee_collection_get_size (self->ro_collection) == 1);
> g_assert (gee_collection_contains (self->ro_collection, "one"));
> </code>
>
> g_test_trap_fork uses fork() to fork the process.
>
> Here is the g_test_trap_fork code if this can enlighten the problem:
> http://git.gnome.org/cgit/glib/tree/glib/gtestutils.c#n1582
>
> I did not yet resolve the problem. I hope I will be able with your help.
>
> Best regards, Didier.
>
>
FWIW, I ran into the same issue and, since I only really care whether an
assert (and thus an abort()) is getting called during a given test, I came
up with the following. This approach doesn't require the forking of a child
process as ASSERT_DEATH does, and so I was able to capture gcov data for the
assert() statement. Note that simply catching SIGABRT wasn't enough,
because abort() still terminates the program after the signal handler
returns (which I don't want), hence the setjmp and longjmp.
static jmp_buf jmpBuf;
void abortHandler(int param)
{
abortCalled = true;
void (*prev_handler)(int);
prev_handler = signal(SIGABRT, abortHandler);
longjmp(jmpBuf, 1);
}
#define ASSERT_ABORT(statement) \
abortCalled = false; \
\
signal(SIGABRT, abortHandler); \
\
if (!setjmp(jmpBuf)) \
{ \
statement; \
} \
\
ASSERT_TRUE(abortCalled);
You can use it it like any other gtest macro:
ASSERT_ABORT(myObject.doSomething());
--Scott