[xml] Bug in configure script's socklen_t test



---THE PROBLEM---

I encountered an error building libxml2, in the course of a konstruct
build:

        ...
         gcc -DHAVE_CONFIG_H -I. -I. -I. -I./include -I./include -D_REENTRANT -O3 ...
        nanohttp.c: In function `xmlNanoHTTPScanAnswer':
        nanohttp.c:785: warning: cast discards qualifiers from pointer target type
        nanohttp.c:811: warning: cast discards qualifiers from pointer target type
        nanohttp.c:836: warning: cast discards qualifiers from pointer target type
        nanohttp.c:842: warning: cast discards qualifiers from pointer target type
        nanohttp.c:848: warning: cast discards qualifiers from pointer target type
        nanohttp.c:854: warning: cast discards qualifiers from pointer target type
        nanohttp.c: In function `xmlNanoHTTPConnectAttempt':
        nanohttp.c:973: error: `len' undeclared (first use in this function)
        nanohttp.c:973: error: (Each undeclared identifier is reported only once
        nanohttp.c:973: error: for each function it appears in.)
        make[2]: *** [nanohttp.lo] Error 1

Line 973 was a local variable declaration of type SOCKLEN_T:

        ...
            if ( FD_ISSET(s, &wfd) ) {
-->             SOCKLEN_T len;
                len = sizeof(status);
        #ifdef SO_ERROR
                if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) {
                    /* Solaris error code */
                    __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
        ...

SOCKLEN_T, as given in config.h, had an empty definition:

        ...
        /* #undef HAVE_LIBHISTORY */
        /* #undef HAVE_LIBREADLINE */
        #define SOCKLEN_T
        #define HAVE_LIBPTHREAD
        #define HAVE_PTHREAD_H
        ...

So I guessed that something had gone wrong with a configure-script test. A
relevant excerpt from config.log:

        ...
        configure:25621: checking for type of socket length (socklen_t)
        configure:25641: gcc -c -O3 -pipe -march=athlon-tbird -mmmx -m3dnow ...
        configure:25635: warning: function declaration isn't a prototype
        configure: failed program was:
        #line 25630 "configure"
        #include "confdefs.h"

        #include <stddef.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        int main() {

        (void)getsockopt (1, 1, 1, NULL, (socklen_t *)NULL)
        ; return 0; }
        ...

(The configure script went on to try "size_t *" and "int *", to no better
effect. Result: "could not determine.")

This had me scratching my head for a while. GCC gave nothing more than a
warning; why did this test fail? I could even compile the test program
manually, and confirm that GCC was returning 0.


---THE ANSWER---

The socklen_t test compile is performed using the custom AC_TRY_COMPILE2
macro (instead of the standard AC_TRY_COMPILE); this macro signals failure
not only if the compile fails, but also if the compiler produces any
terminal output whatsoever. The idea is that a mismatched type on the fifth
argument of getsockopt() will produce a compiler warning---which in this
case correctly indicates a failure of the test---whereas the correct type
will compile without any warnings at all.

UNLESS, of course, something else in the test program produces a warning...
which will then cause all variations of the fifth argument type to fail.
Something like the non-prototypical main() declaration, perhaps? That would
not pose a problem for most people, since GCC doesn't print warnings for
non-prototype declarations by default. I set CFLAGS in my .bashrc,
however---and I keep a scary-looking set of -Wxxx flags in it.


---THE SOLUTION---

A one-line patch is attached, against acinclude.m4. It will change the "int
main()" declaration in the test program body to "int main(void)"; this much
solves the problem on my end.

Beyond that, I would suggest tweaking the socklen_t test clause in
configure.in to bomb out with an AC_MSG_ERROR instead of an AC_MSG_WARN if
it can't determine a value for SOCKLEN_T. It should not be possible for
the configure script to produce a config.h file as previously described.
(Maybe it could fall back to "#define SOCKLEN_T int", etc.---anything so
long as it doesn't leave the code in an uncompilable state.)

And even further... I came across this message/thread in the mailing list
archive, from nearly three years ago:

        http://mail.gnome.org/archives/xml/2001-August/msg00061.html

I would agree that the socklen_t test code is icky, but more so than that,
I would say it is rather fragile for what it's trying to do. Can one really
be sure that a given snippet of code will compile with no warnings at all?
Or heck, what about vendor compilers that print out a "Evaluation version:
please contact Yoyodyne Inc. for a permanent license" header on every
invocation? The possibilities are endless....

So far as I've seen, the approach Albert Chin was proposing---having the
compiler check for a prototype mismatch---is Autoconf's usual MO. I can
understand not wanting to fix what's not broken, but the test as currently
written feels like a shoe waiting to drop. I'm surprised that relatively
few people seem to have had a problem with it.


Anyway, I hope this has been of some usefulness. Please Cc: any replies to
me, as I am not subscribed to this list.


Regards,


--Danny


-- 
NAME   = Daniel Richard G.       ##  Remember, skunks       _\|/_  meef?
EMAIL1 = skunk iskunk org        ##  don't smell bad---    (/o|o\) /
EMAIL2 = skunk alum mit edu      ##  it's the people who   < (^),>
WWW    = http://www.******.org/  ##  annoy them that do!    /   \
--
(****** = site not yet online)

Attachment: fix-socklen_t-test.patch
Description: Text document



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]