oetiker / rrdtool-1.x

RRDtool 1.x - Round Robin Database
http://www.rrdtool.org
GNU General Public License v2.0
1k stars 262 forks source link

Broken isinf on Solaris 9 #271

Closed oetiker closed 12 years ago

oetiker commented 12 years ago

The current implementation of isinf on Solaris 9 leads to the problem that valid line numbers are rejected as "out of range" as outlined in this bug reported for Orca:

The error message is {{{ LINE width '1:average1#0000ff:Zero-fill-on-demand' is out of range in line 'LINE1:average1#0000ff:Zero-fill-on-demand' }}}

The code leading to this message is from rrd_graph_helper.c: {{{ case GF_LINE: if (c1 == ':') { gdp->linewidth = 1; dprintf("- using default width of 1\n"); } else { i = 0; sscanf(&line[_eaten], "%lf:%n", &gdp->linewidth, &i); fprintf(stderr,"LF: %lf\n", gdp->linewidth); fprintf(stderr,"I: %ld %ld %ld\n",fpclass(gdp->linewidth),FP_SNAN,FP_QNAN); if (!i) { rrd_set_error("Cannot parse line width '%s' in line '%s'\n", &line[_eaten], line); return 1; } else { dprintf("- scanned width %f\n", gdp->linewidth); if (isnan(gdp->linewidth)) { rrd_set_error ("LINE width '%s' is not a number in line '%s'\n", &line[_eaten], line); return 1; } if (isinf(gdp->linewidth)) { rrd_set_error ("LINE width '%s' is out of range in line '%s'\n", &line[_eaten], line); return 1; } if (gdp->linewidth < 0) { rrd_set_error ... }}}

The problem is the broken implementation of 'isinf' for Solaris 9 in rrd_config_bottom.h: {{{ /* for Solaris */

if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))

define HAVE_ISINF 1

ifdef isinf

undef isinf

endif

define isinf(a) (!!(fpclass(a) & (FP_SNAN|FP_QNAN)))

endif

}}}

The problem is that fpclass(a) does not return a bitmask, but a number indicating the class of the floatingpoint number as documented in fpclass(3c): {{{ The fpclass() function returns one of the following classes to which dsrc belongs: }}} These are from /usr/include/ieeefp.h and valid results: {{{ typedef enum fpclass_t { FPSNAN = 0, /* signaling NaN / FPQNAN = 1, / quiet NaN _/ FPNINF = 2, / negative infinity _/ FPPINF = 3, / positive infinity _/ FPNDENORM = 4, / negative denormalized non-zero _/ FPPDENORM = 5, / positive denormalized non-zero _/ FPNZERO = 6, / -0.0 _/ FPPZERO = 7, / +0.0 _/ FPNNORM = 8, / negative normalized non-zero _/ FPPNORM = 9 / positive normalized non-zero */ } fpclass_t; }}}

This alternative implementation for isinf solves the problem: {{{

define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)

}}}

oetiker commented 12 years ago

[oetiker] indeed ... bad bug ... a regression introduced by a bad optimization added r1904 ... fixed in r2093 ... thanks