On 2015/10/02 13:35, L. V. Lammert wrote:
> Hi Stuart,
> 
> One final question that is bugging me - if you have a few moments to
> provide a little edumification it would be appreciated.
> 
> I realize that there is a issue for the project with time and resources
> to build binary packages packages for every 32-bit flavor,

Not a big problem for i386, it takes about 22 hours to do a full
package build on the project's i386 build machines at present.

>                                                            .. but I would
> have thought building from *source* would allowt the build process to pull
> the correct time_t definition from the headers ON the 32-bit system to
> build correctly?
> 
>       Thanks!
> 
>       Lee

It uses the correct time_t definition which means the variable that
timestamps are stored in are, correctly, 64-bit. But it tries to
format it using a format string like %lu that only uses 32 bits of
the value, leaving the rest for the next part of the format string.

Demo program.

cat << EOF > a.c
#include <stdio.h>

main() {
        time_t a = 123456789123456789LL;
        printf("%lu %lu %lu\n", a, a, a);
}
EOF

On amd64 all is well:

$ make a CFLAGS=-Wformat
$ ./a
123456789123456789 123456789123456789 123456789123456789

On i386 it's not so good:

$ make a CFLAGS=-Wformat
cc -Wformat   -o a a.c
a.c: In function 'main':
a.c:5: warning: format '%lu' expects type 'long unsigned int', but argument 2 
has type 'time_t'
a.c:5: warning: format '%lu' expects type 'long unsigned int', but argument 3 
has type 'time_t'
a.c:5: warning: format '%lu' expects type 'long unsigned int', but argument 4 
has type 'time_t'
$ ./a
2899336981 28744523 2899336981

.....

Converted to hex so you can see where these numbers are coming from:

$ moo -b 16 123456789123456789
0x1b69b4bacd05f15

       $ moo -b 16 2899336981
       0xacd05f15

$ moo -b 16 28744523
0x1b69b4b

So you're already getting wrong values. But now consider the case when
you want to also print a string, so have a %s after these:

        time_t a = 123456789123456789LL;
        char *b = "testing...";
        printf("%lu %lu %lu %s\n", a, a, a, b);

...that is passed by address not value, but printf is 'out of sync',
it's still looking at half of the second occurrence of 'a' (0x1b69b4b)
So it tries to go and read characters from that address which is
very unlikely to be in the program's address space : boom

$ ./b
Segmentation fault (core dumped) 

It's fixable, the fixes are all very simple, see the patches to icinga
in the ports tree - but it's tedious and there are a lot of them.
Logging. CGIs. Saving status data to files. So between Nagios' lack
of working reliably for me in the past (I had a few occasions where
it claimed to be running OK but wasn't actually doing checks - and
of course something important broke at the time) - and their nasty
attitude towards forks and towards the monitoring-plugins (formerly
nagios-plugins) and monitoring-exchange (formerly nagios-exchange)
people, I felt there were better ways to spend my time.

Reply via email to