[nanomsg] patch for incorrect configure guess for NN_HAVE_ATOMIC_SOLARIS

  • From: Mark Mitchell <mark.mitchell@xxxxxxxxxxxxx>
  • To: "nanomsg@xxxxxxxxxxxxx" <nanomsg@xxxxxxxxxxxxx>
  • Date: Fri, 11 Jul 2014 14:42:08 -0500

When trying to cross-compile nanomsg using GCC for a Linux system using
uclibc, and running on a MIPS architecture, the link step fails with an
undefined reference to `atomic_add_32_nv':

  ./doltlibtool  --tag=CC   --mode=link 
/opt/broadcom/bcm685xx/usr/bin/mips-unknown-linux-uclibc-gcc -std=gnu99  -Os -g 
-ggdb -g3 -pthread   -o nanocat tools/nanocat.o tools/options.o libnanomsg.la 
-lrt
  libtool: link: /opt/broadcom/bcm685xx/usr/bin/mips-unknown-linux-uclibc-gcc 
-std=gnu99 -Os -g -ggdb -g3 -pthread -o .libs/nanocat tools/nanocat.o 
tools/options.o  ./.libs/libnanomsg.so -lrt -pthread
  ./.libs/libnanomsg.so: undefined reference to `atomic_add_32_nv'
  collect2: ld returned 1 exit status
  make: *** [nanocat] Error 1
  Command returned 2


This is because NN_HAVE_ATOMIC_SOLARIS is defined during the
configure stage, resulting in NN_ATOMIC_SOLARIS being defined in
src/utils/atomic.h, resulting in a reference to atomic_add_32_nv in
src/utils/atomic.c.

Output from build shows both -DNN_HAVE_GCC_ATOMIC_BUILTINS=1 and
-DNN_HAVE_ATOMIC_SOLARIS=1 :

  ./doltlibtool  --tag=CC   --mode=compile 
/opt/broadcom/bcm685xx/usr/bin/mips-unknown-linux-uclibc-gcc -std=gnu99 
-DPACKAGE_NAME=\"nanomsg\" -DPACKAGE_TARNAME=\"nanomsg\" 
-DPACKAGE_VERSION=\"0.4-beta-38-ge0224a1-dirty\" -DPACKAGE_STRING=\"nanomsg\ 
0.4-beta-38-ge0224a1-dirty\" -DPACKAGE_BUGREPORT=\"nanomsg@xxxxxxxxxxxxx\" 
-DPACKAGE_URL=\"http://nanomsg.org/\"; -DPACKAGE=\"nanomsg\" 
-DVERSION=\"0.4-beta-38-ge0224a1-dirty\" -DNN_HAVE_GCC=1 -DNN_HAVE_LINUX=1 
-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 
-DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 
-DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_NETDB_H=1 
-DHAVE_ARPA_INET_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_SOCKET_H=1 
-DHAVE_SYS_IOCTL_H=1 -DHAVE_STDINT_H=1 -DNN_HAVE_STDINT=1 -DHAVE_PIPE=1 
-DNN_HAVE_PIPE=1 -DHAVE_PIPE2=1 -DNN_HAVE_PIPE2=1 -DNN_HAVE_CLOCK_MONOTONIC=1 
-DHAVE_LIBRT=1 -DHAVE_CLOCK_GETTIME=1 -DHAVE_POLL=1 -DNN_HAVE_POLL=1 
-DHAVE_EPOLL_CREATE=1 -DNN_USE_EPOLL=1 -DNN_USE_LITERAL_IFADDR=1 
-DHAVE_ACCEPT4=1 -DNN_HAVE_ACCEPT4=1 -DNN_HAVE_SOCKETPAIR=1 
-DNN_HAVE_SEMAPHORE=1 -DNN_HAVE_GCC_ATOMIC_BUILTINS=1 
-DNN_HAVE_ATOMIC_SOLARIS=1 -DNN_USE_PIPE=1 -DHAVE_DLFCN_H=1 
-DLT_OBJDIR=\".libs/\" -I. -I/home/source/nanomsg   -D_GNU_SOURCE -D_GNU_SOURCE 
-DNN_EXPORTS -Os -g -ggdb -g3 -pthread -MT src/utils/libnanomsg_la-atomic.lo 
-MD -MP -MF src/utils/.deps/libnanomsg_la-atomic.Tpo -c -o 
src/utils/libnanomsg_la-atomic.lo `test -f 'src/utils/atomic.c' || echo 
'/home/source/nanomsg/'`src/utils/atomic.c
  /home/source/nanomsg/src/utils/atomic.c: In function 'nn_atomic_inc':
  /home/source/nanomsg/src/utils/atomic.c:46:5: warning: implicit declaration 
of function 'atomic_add_32_nv' [-Wimplicit-function-declaration]


When both NN_HAVE_GCC_ATOMIC_BUILTINS and NN_HAVE_ATOMIC_SOLARIS
are defined, the order of if/else logic in atomic.h
causes NN_HAVE_ATOMIC_SOLARIS to be used in preference to
NN_HAVE_GCC_ATOMIC_BUILTINS. This is giving incorrect results
for a Linux system with a libc which has no such functions like
atomic_add_32_nv().

The reason both NN_HAVE_GCC_ATOMIC_BUILTINS and NN_HAVE_ATOMIC_SOLARIS
result defined is related to this part of nanomsg configure.ac:

  AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
          #include <stdint.h>
          int main()
          {
              volatile uint32_t n = 0;
              __sync_fetch_and_add (&n, 1);
              __sync_fetch_and_sub (&n, 1);
              return 0;
          }
  ]])], [
      AC_DEFINE([NN_HAVE_GCC_ATOMIC_BUILTINS])
  ])

  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
      [[#include <atomic.h>]],
      [[uint32_t value; atomic_cas_32 (&value, 0, 0); return 0;]])],[
      AC_DEFINE([NN_HAVE_ATOMIC_SOLARIS])],[])

And:

There exists an 'atomic.h' in the include path of the GCC toolchain
I am using. This allows the AC_COMPILE_IFELSE to succeed, which
results in NN_HAVE_ATOMIC_SOLARIS being defined regardless of whether
the preceding test for NN_HAVE_GCC_ATOMIC_BUILTINS succeeded.

The reason this configure bug is not obvious on a typical x86 glibc
Linux system is there is no 'atomic.h' in /usr/include, so the
AC_COMPILE_IFELSE will fail with "fatal error: atomic.h: No such file or
directory", resulting in NN_HAVE_ATOMIC_SOLARIS not being defined, and
only NN_HAVE_GCC_ATOMIC_BUILTINS being defined, which by coincidence,
is the proper definition.

If the test is changed from AC_COMPILE_IFELSE to AC_LINK_IFELSE, then
then even though the configure test compiles, it will (correctly) fail
to link with my MIPS cross-toolchain due to undefined atomic_cas_32,
and NN_HAVE_ATOMIC_SOLARIS will not be defined. Then there will be no
incorrect reference to non-existing function atomic_add_32_nv() and
nanomsg builds correctly.

The following one-line patch to configure.ac eliminates the spurious
definition of NN_HAVE_ATOMIC_SOLARIS:

diff --git a/configure.ac b/configure.ac
index 853a4ba..781f9f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -321,7 +321,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
     AC_DEFINE([NN_HAVE_GCC_ATOMIC_BUILTINS])
 ])

-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+AC_LINK_IFELSE([AC_LANG_PROGRAM(
     [[#include <atomic.h>]],
     [[uint32_t value; atomic_cas_32 (&value, 0, 0); return 0;]])],[
     AC_DEFINE([NN_HAVE_ATOMIC_SOLARIS])],[])

However, this is probably not a proper fix. Probably a more
proper fix would be to change the configure.ac logic so if
NN_HAVE_GCC_ATOMIC_BUILTINS is defined, then the test for
NN_HAVE_ATOMIC_SOLARIS is not even performed. But I'm not an autotools
expert and a proper fix is best left up to someone who is an autotools
expert.

To summarize, what is clear is:

1. What configure.ac is testing for (mere presence of atomic.h header) is
   not consistent with what atomic.c presumes NN_HAVE_ATOMIC_SOLARIS
   indicates (existence of a function named atomic_add_32_nv).

2. The configure gives incorrect results with the GCC MIPS
   cross-toolchain and libc I am using, and thus the build is broken.

It also seems clear that defining both NN_HAVE_GCC_ATOMIC_BUILTINS
and NN_HAVE_ATOMIC_SOLARIS does not make sense, as it will result in
incorrect behavior on some systems.

The solution is to fix the incorrect logic in configure.ac.


 The information contained in this message may be confidential, privileged or 
protected from disclosure. If you have received it by mistake, please let us 
know by e-mail reply and delete it from your system; you may not copy, 
disseminate or disclose the contents of this message to anyone

Other related posts:

  • » [nanomsg] patch for incorrect configure guess for NN_HAVE_ATOMIC_SOLARIS - Mark Mitchell