Search code examples
memory-leaksvalgrindexit-code

Valgind: non-zero exit code only if memory is definitely lost


We use valgrind as a part of our CI process. If there are some memory problems, valgrind must return non-zero code, and this incident is reported. This is how we run it:

valgrind --error-exitcode=1 --tool=memcheck --leak-check=full \
    --errors-for-leak-kinds=definite --show-leak-kinds=definite \
    --track-origins=yes ./some_cgo_application

(...)

==25182== HEAP SUMMARY:
==25182==     in use at exit: 2,416,970 bytes in 34,296 blocks
==25182==   total heap usage: 83,979 allocs, 49,684 frees, 5,168,335 bytes allocated
==25182== 
==25182== LEAK SUMMARY:
==25182==    definitely lost: 0 bytes in 0 blocks
==25182==    indirectly lost: 0 bytes in 0 blocks
==25182==      possibly lost: 3,024 bytes in 7 blocks
==25182==    still reachable: 2,413,946 bytes in 34,289 blocks
==25182==                       of which reachable via heuristic:
==25182==                         newarray           : 520 bytes in 1 blocks
==25182==         suppressed: 0 bytes in 0 blocks
==25182== Reachable blocks (those to which a pointer was found) are not shown.
==25182== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==25182== 
==25182== For counts of detected and suppressed errors, rerun with: -v
==25182== ERROR SUMMARY: 20 errors from 5 contexts (suppressed: 0 from 0)

Currently we're interested only in memory that is definitly lost. If no blocks are definitly lost, valgrind's exit code is expected to be zero. However, it returns 1 despite of the options --errors-for-leak-kinds=definite --show-leak-kinds=definite.

echo $?
1

Are thery any other options that will help to achieve the desired result?


Solution

  • I suspect the exit status 1 comes from the program itself. I can reproduce this with:

    $ valgrind --error-exitcode=1 --tool=memcheck --leak-check=full \
      --errors-for-leak-kinds=definite --show-leak-kinds=definite \
      --track-origins=yes /bin/false
    

    This does not look like something that can be changed in the current sources:

       case VgSrc_ExitProcess: /* the normal way out (Darwin) */
          /* Change the application return code to user's return code,
             if an error was found */
          if (VG_(clo_error_exitcode) > 0 
              && VG_(get_n_errs_found)() > 0) {
             VG_(client_exit)( VG_(clo_error_exitcode) );
          } else {
             /* otherwise, return the client's exit code, in the normal
                way. */
             VG_(client_exit)( VG_(threads)[tid].os_state.exitcode );
          }
    

    And this exitcode member is set from the sys_exit_group wrapper in coregrind/m_syswrap/syswrap-linux.c, without any way to tweak it.

    Considering this, I think your best bet (without patching valgrind) is to select an exit status different from any exit status your program might use, and use that as an indicator of a valgrind error.