11

I have C/C++ code coverage setup with gcov for several files in the project. The executables are being run in parallel. This results in some shared piece of code to be run in parallel.

I am getting corrupt .da files or zero sized .da files. Is this a problem on parallel run?

Because two or more executable instance is trying to write on the same .da file for writing the coverage count for each statement in execution?

If so, is there any workaround?

Gcov version being used is 1.5

simonc
  • 41,632
  • 12
  • 85
  • 103
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • 1
    How about changing whatever script you're using to run the coverage tests, so that each run (no matter if they're parallel or not) uses different result files? – Some programmer dude Feb 01 '13 at 09:57
  • But for running different test cases, would like to get cumulative counter values to see the coverage analysis. The shared portion of code happens to be run in parallel resulting in accessing the same .da files simultaneously. This could result in the corruption. Any help to get this done in parallel avoiding the contention? – Dr. Debasish Jana Feb 01 '13 at 11:07
  • Well, gcov is open source. Presumably you can modify it to lock the files, although I'd expect that to not help much, if it only opens the file once per run. There are other c/c++ coverage tools that will collect test coverage data for "independent" runs and combine those seperate sets of data into a single set, giving you unified overview. – Ira Baxter Feb 01 '13 at 11:12
  • Is there any opensource/freeware tool that can be run thread-safe? Or any other gcov options to allow incrementing statement hit counts in parallel? Especially, for shared library, the code coverage statistics on parallel run would be a plus. – Dr. Debasish Jana Feb 01 '13 at 11:58
  • The ones I know about are not open source. – Ira Baxter Feb 01 '13 at 14:27
  • Has anyone ever managed to achieve this? – Arno Moonen Aug 19 '15 at 07:58
  • @ArnoMoonen there are three solutions posted below. – yugr Jan 09 '22 at 06:30

3 Answers3

6

I had a similar need and I solved it by setting up the GCOV_PREFIX environment variable.

According to the documentation:

GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. Prefix can be absolute, or relative. The default is no prefix.

Setting GCOV_PREFIX to a custom directory, unique for each executable+execution, will force the runtime to generate '.gcda' in the specified directory instead of using the compilation one (where the '.gcno' are).

Once all the executions completed you'll be able to use them to generate the merged-run report.

Adriano
  • 487
  • 4
  • 8
  • 1
    Thank you! Setting `GCOV_PREFIX_STRIP` together with `GCOV_PREFIX` enabled me to place the `.gcda`-files for each test in a separate directory. No I only have to figure out how to combine them. Then I can run all my tests in parallel. – thoni56 Apr 15 '20 at 08:17
  • 2
    According to my findings you have to keep the `.gcno` and the generated `.gcda` together. Rather than copying the `.gcda` to where the objects and `.gcno` are, I copied the `.gcno` to the directory of the `.gcda`. In this way I could create coverage info for each test separately. I could also combine all info using `lcov -o total.coverage -a -a ...`. – thoni56 Apr 15 '20 at 14:21
3

Well it seems you have already figured the root cause of the problem and looking for the work around.
I have successfully configured few projects for code coverage with gcov.
I would like to clear few things for you:

  • we get .gcno files for each of the source files instrumented with --coverage option during compilation.
  • And at the time of execution we get .gcda files for each one of gcno files.

.gcno files are just flow charts structure of the relevant source code files.
.gcda files are the actual coverage data generated at the time of execution.

So, in your situation .gcda (used to be .da in earlier versions) are having conflicts when two or more execution tries to write the same .gcda file simultaneously.

Simplest work around would be running the tests serially. (At least that's what I did )
you don't need to worry about losing coverage data as .gcda gets appended with every execution and not overwritten. Keep this in mind that you don't have to do re-compilation because it would change the .gcno files and the .gcda files from before will become useless.

dwj
  • 3,443
  • 5
  • 35
  • 42
Vikas Tawniya
  • 1,323
  • 1
  • 13
  • 22
  • "Simplest work around would be running the tests serially" - unfortunately this isn't going to work for recursive programs (e.g. `clang`). – yugr Jan 06 '22 at 09:43
1

Yet another solution in newer (9+) versions of GCC support %p pattern in -fprofile-dir:

-fprofile-dir=coverage.%p

This allows one to avoid explicitly regenerating GCOV_PREFIX environment variables each time. It also enables profiling of more complex usecases e.g. running same program/library recursively (clang and gcc are like this).

Once you collect the coverage, you can combine it with the help of gcov-tool-many (which is a wrapper over gcov-tool which can only combine two profiles at a time):

# Combine coverages
$ scripts/gcov-tool-many merge coverage.*
# Get rid of mangled names like #home#user#myproject#bin#main.gcda
for f in `find -name '#*.gc[dn][ao]'`; do
  mv $f $(basename $f | tr \# /)
done
# Generate the report
gcov *.gcno
yugr
  • 19,769
  • 3
  • 51
  • 96