A colleague asked for help finding a tough-to-reproduce SIGSEGV in a program, so I'm running it through valgrind
to look for any memory issues.
Unfortunately, I end up with this:
$ valgrind --track-origins=yes sim-server
==128768==
==128768== More than 10000000 total errors detected. I'm not reporting any more.
==128768== Final error counts will be inaccurate. Go fix your program!
==128768== Rerun with --error-limit=no to disable this cutoff. Note
==128768== that errors may occur in your program without prior warning from
==128768== Valgrind, because errors are no longer being displayed.
==128768==
Everything I can see comes from libasound.2.0.0
or libportaudio.so.2.0.0
and they all have the same warning:
Conditional jump or move depends on uninitialized value(s)
Example:
==130835== Conditional jump or move depends on uninitialised value(s)
==130835== at 0x483865C: malloc (vg_replace_malloc.c:306)
==130835== by 0x483ADE7: realloc (vg_replace_malloc.c:834)
==130835== by 0x48A209A: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x48A251F: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x48A5944: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x4878EA6: start_thread (pthread_create.c:477)
==130835== by 0x4CECA2E: clone (clone.S:95)
==130835== Uninitialised value was created by a stack allocation
==130835== at 0x4E626C0: ??? (in /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0)
After installing libportaudio2-dbysym
and libasound2-dbgsym
, that becomes:
==135367== Thread 3:
==135367== Conditional jump or move depends on uninitialised value(s)
==135367== at 0x483865C: malloc (vg_replace_malloc.c:306)
==135367== by 0x483ADE7: realloc (vg_replace_malloc.c:834)
==135367== by 0x48A209A: PaAlsaStreamComponent_RegisterChannels (pa_linux_alsa.c:4003)
==135367== by 0x48A251F: PaAlsaStream_SetUpBuffers (pa_linux_alsa.c:4114)
==135367== by 0x48A5944: CallbackThreadFunc (pa_linux_alsa.c:4355)
==135367== by 0x4878EA6: start_thread (pthread_create.c:477)
==135367== by 0x4CECA2E: clone (clone.S:95)
==135367== Uninitialised value was created by a stack allocation
==135367== at 0x4E626C0: refine_back_time_and_size (pcm_ioplug.c:263)
I can see three logical explanations:
libportaudio2
+libasound2
are volatile and unusable dependencies that could crash at any moment
libasound2
Pa_Initialize()
which is not a function that requires me to set anything up ahead of time.How can I suppress Conditional jump or move...
warnings originating from libportaudio.so.2.0.0
in Valgrind?
Using this answer, Valgrind's documentation on supressing errors and Valgrind's documentation on writing suppression files, I've come up with this:
$ cat suppress.val
{
ignore_asound_cond_jump_0
Memcheck:Cond
obj:*/libasound.so*
}
{
ignore_pa
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
ignore_pcm
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pulse.so
}
{
ignore_pa_8
Memcheck:Value8
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
ignore_pulse
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/libpulse.so.0.23.0
}
{
ignore_pulsecommon
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
}
{
ignore_asound_ioctl
Memcheck:Param
ioctl(generic)
fun:*
obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0
}
{
ignore_pa_poll
Memcheck:Param
poll(timeout)
fun:*
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
ignore_pa_malloc
Memcheck:Param
malloc
fun:*
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
$ valgrind --suppressions=suppress.val --track-origins=yes sim-sound
...
--135517--
--135517-- used_suppression: 27290 ignore_asound_cond_jump_0 suppress.val:2
--135517-- used_suppression: 7914 ignore_pulsecommon suppress.val:27
--135517-- used_suppression: 17884 ignore_pcm suppress.val:12
--135517-- used_suppression: 471481 ignore_pa suppress.val:7
--135517-- used_suppression: 3518 ignore_pulse suppress.val:22
--135517-- used_suppression: 1760 ignore_pa_8 suppress.val:17
--135517-- used_suppression: 606 ignore_pa_poll suppress.val:45
--135517-- used_suppression: 22 ignore_asound_ioctl suppress.val:38
==135517==
==135517== ERROR SUMMARY: 60721 errors from 7 contexts (suppressed: 530475 from 1044)
That takes care of a lot of warnings, but the malloc
one described above is not suppressed. It's not just malloc, others such as memmove
from vg_replace_strmem.c
is also an offender. Those source files are not in my program and the stack allocation is not in my program. I've been playing with the ignore_pa_malloc
receipie, but I'm really having trouble finding a rule set that will work.
Paul Floyd has a suggestion about how to fix the problem. That's probably better. This answers how to suppress the error. Note that if there is a problem with the portaudio integration, this could mask that problem.
The trick was to use a literal "...
" line in the suppression file.
The following rule says: Ignore "Conditional jump or move depends on uninitialised value(s)" errors that occur within libportaudio.so.2.0.0
.
{
ignore_pa
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
However, the following occurs in libc.so
:
==130835== Conditional jump or move depends on uninitialised value(s)
==130835== at 0x483865C: malloc (vg_replace_malloc.c:306)
==130835== by 0x483ADE7: realloc (vg_replace_malloc.c:834)
==130835== by 0x48A209A: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x48A251F: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x48A5944: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835== by 0x4878EA6: start_thread (pthread_create.c:477)
==130835== by 0x4CECA2E: clone (clone.S:95)
The answer is a slight change to the recepie:
{
ignore_pa
Memcheck:Cond
...
obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
The ...
will cause us to ignore any Memcheck:Cond
for any error with libportaudio.so.2.0.0
in the stack. This means errors in libc.so
will not be raised if they came through libportaudio.so.2.0.0
.
When reading documentation I thought ...
was just a truncation, but it's actually literal. The Valgrind documentation says:
A location line may also be simply "..." (three dots). This is a frame-level wildcard, which matches zero or more frames. Frame level wildcards are useful because they make it easy to ignore varying numbers of uninteresting frames in between frames of interest. That is often important when writing suppressions which are intended to be robust against variations in the amount of function inlining done by compilers.