Christopher Layne wrote:
> On Sat, Aug 04, 2007 at 07:21:46PM -0700, Scott Lamb wrote:
>> Christopher Layne wrote:
>>> On Thu, Jul 19, 2007 at 01:14:58PM -0700, Scott Lamb wrote:
>>>> When I use "valgrind --tool=memcheck" on a libevent-based program, it
>>>> gives the following complaint:
>>>>
>>>> ==15442== Conditional jump or move depends on uninitialised value(s)
>>>> ==15442==    at 0x4C0F2D3: event_add (event.c:632)
>>>> ==15442==    by 0x405EE4: main_loop (net.c:356)
>>>> ==15442==    by 0x411853: main (tincd.c:329)
>>>>
>>>> Here's the relevant portion of event.c:
>>>>
>>>> 632                if ((ev->ev_flags & EVLIST_ACTIVE) &&
>>>> 633                    (ev->ev_res & EV_TIMEOUT)) {
>>>>
>>>> I've looked through the libevent code and verified that ev_res is always
>>>> initialized when (ev_flags & EVLIST_ACTIVE) is true, so there's no real
>>>> bug here.
>>> You wouldn't happen to have a copy of the code or atleast code segment
>>> which was tickling this would you?
>> Yes, I also think it was really an uninitialized area being read from, 
>> but not one to worry about.
>>
>> As I'm sure you know, && indicates lazy evaluation - the second half 
>> doesn't get evaluated if the first half is false. But this was an 
> 
> Right. However my point (in regards to splitting the conditional) was due
> to the ambiguity of multiple options when valgrind complains about a single
> line which has more than one possibility:
> 
> 1. ev_flags is uninitialised (but when masked, result just happens to be 
> true).
>      + ev_res is uninitialised, valgrind complains about line 632.
> 2. ev_flags is uninitialised, mask results false, ev_res never touched, 
> valgrind
>    complains about line 632.
> 3. ev_flags is initialised, mask results true, ev_res is uninitialised, 
> valgrind
>    complains about line 632.
> 4. ev_flags is initialised, mask results false, ev_res never touched.
> 
> See where I was going with that now? The code may indicate all day that
> ev_flags should always be initialised before even hitting event_add, but that
> doesn't stop other things from happening, like half your DRAM being 0x0,
> your CPU melting, straight up bugs, etc. I'm sure you get the drift.

Well, splitting the conditional won't help - line numbers in optimized
builds don't really make sense anyway; it jumps all over the place. This
only happens on optimized 64-bit builds (in which the optimization makes
sense because ev_flags and ev_res are in the same word). If you have
such a machine, you can reproduce it with this trivial program:

[EMAIL PROTECTED] ~]$ cat test.c
#include <stdlib.h>

#include <event.h>

int
main(int argc, char **argv)
{
    struct event *ev;

    ev = malloc(sizeof(struct event));
    if (ev == NULL)
        abort();

    ev->ev_flags = 0;

    if ((ev->ev_flags & EVLIST_ACTIVE) &&
        (ev->ev_res & EV_TIMEOUT)) {
        abort();
    }

    return 0;
}
[EMAIL PROTECTED] ~]$ uname -a
Linux rosalyn.zorg.slamb.org 2.6.18-8.el5xen #1 SMP Thu Mar 15 19:56:43
EDT 2007 x86_64 x86_64 x86_64 GNU/Linux
[EMAIL PROTECTED] ~]$ gcc --version
gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[EMAIL PROTECTED] ~]$ valgrind --version
valgrind-3.2.1
[EMAIL PROTECTED] ~]$ gcc -Wall -O2 test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate...
==24325== Conditional jump or move depends on uninitialised value(s)
==24325==    at 0x400504: main (in /home/slamb/test)
...
[EMAIL PROTECTED] ~]$ gcc -Wall test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...



You'll notice the same thing does not happen on a 32-bit machine.

[EMAIL PROTECTED] ~]$ uname -a
Linux spiff-centos5 2.6.23-rc1 #8 SMP Fri Jul 27 21:02:53 PDT 2007 i686
i686 i386 GNU/Linux
[EMAIL PROTECTED] ~]$ gcc --version
gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[EMAIL PROTECTED] ~]$ valgrind --version
valgrind-3.2.1
[EMAIL PROTECTED] ~]$ gcc -Wall -O2 test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...
[EMAIL PROTECTED] ~]$ gcc -Wall test.c -o test
[EMAIL PROTECTED] ~]$ valgrind --tool=memcheck ./test
...boilerplate only...

> I still do not believe this to be valgrind's fault. Valgrind surely knows 
> exactly
> what is going on with registers as it is emulating them.
> (http://valgrind.org/docs/manual/mc-tech-docs.html#mc-tech-docs.storage)

It's not quite sophisticated enough to realize that despite boolean
operations before performed on junk, they can never actually influence
the result.

> I basically was just curious how you got it to come about, because I also
> tried various optimization combinations of both libevent (ev_res not init'd)
> and test code to try and see this and was unsuccessful in doing so. Valgrind
> never indicated an error. Now if I explicitly did not pass the event struct
> to event_set() before hand, then yes errors were visible. But for the most
> part, depending on how much trash was in memory at the time, they wouldn't
> make it past the first assert(). The issue though is that in your case, it
> might not have even been on the stack, or an entirely different scenario -
> which is what got me asking in the first place. I just think it's unsafe
> to write things off as "valgrind noise" when said noise could actually
> indicate a "should not happen."

_______________________________________________
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users

Reply via email to