Subject: guile 3.0.2 segfaults on FreeBSD 9

From: "Jim Pryor" <[email-masked]>
Date: Tue, 06 Dec 2011 10:53:23 -0500

Hi I'm trying to build guile 3.0.2 on FreeBSD and am having some
problems. These are different than what's reported here
<http://savannah.gnu.org/bugs/?func=detailitem&item_id=33082>.

I'm running a custom kernel on FreeBSD 9-STABLE.

The latest packaging script is from guile 1.8.8 back in July 2011. Here
are some changes I made to the packaging script:

* added dependency on libunistring and the threaded version of the Boehm
GC library.
* added a patch to configure.ac, and requested the running of autoconf
and autoheader before the configure stage
* deleted some seemingly obsolete BSD patches (Specifically, I disabled
patches to Makefile.{am,in} and libguile/{eval,read,gc_os_dep}.c. I
folded a patch that formerly was applied to libguile/gc.c into a patch
to libguile/threads.c, which is where the code seems to have moved. And
I disabled patches to config.h.in and configure, since I think these
changes are now generated when we run autoconf and autoheader against
the patched configure.ac)
* had to remove one block from a patch to libguile/threads.c

The patch I made to configure.ac, and the remaining FreeBSD patches to a
few other files, are appended to the end of this email. Additionally,
the BSD packaging script runs this bit of code:

        REINPLACE_FILES=        libguile/smob.c libguile/gc.c \
                                libguile/mallocs.c libguile/gc-malloc.c

        post-extract:
                @find ${WRKSRC}/doc -name "*.info*" -delete

        post-patch:
                @cd ${WRKSRC} ; sed -e 's|<malloc\.h>|<stdlib.h>|g'
                ${REINPLACE_FILES}
                @sed -e 's|2.63|%%AUTOCONF_VERSION%%|g'
                ${WRKSRC}/aclocal.m4

I was able to compile all the .o files,  but was getting linking errors:

    CCLD   guile
    ./.libs/libguile-2.0.so: undefined reference to
    `GC_unregister_my_thread'
    ./.libs/libguile-2.0.so: undefined reference to `GC_pthread_create'
    ./.libs/libguile-2.0.so: undefined reference to
    `GC_register_my_thread'
    ./.libs/libguile-2.0.so: undefined reference to `GC_pthread_detach'
    gmake[3]: *** [guile] Error 1
    gmake[3]: Leaving directory
    `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile'
    gmake[2]: *** [all] Error 2
    gmake[2]: Leaving directory
    `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile'
    gmake[1]: *** [all-recursive] Error 1
    gmake[1]: Leaving directory
    `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3'
    gmake: *** [all] Error 2
    *** Error code 1

    Stop in /usr/ports/lang/guile.

until I made this change in the configure.ac file:

    -PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
    +PKG_CHECK_MODULES([BDW_GC], [bdw-gc-threaded])

Indeed the relevant symbols are located in the libraries installed by
our boehm-gc-threaded package, not the libraries installed by our
boehm-gc package.

OK, so with that change I can compile and link guile just fine. But when
I try to run it, I get a segfault. I noticed this because the `make`
process never even finishes. We get:

          SNARF  posix.doc
          SNARF  net_db.doc
          SNARF  socket.doc
          SNARF  regex-posix.doc
          GEN    guile-procedures.texi
        Segmentation fault (core dumped)
        gmake[3]: *** [guile-procedures.texi] Error 1
        gmake[3]: Leaving directory
        `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile'
        gmake[2]: *** [all] Error 2
        gmake[2]: Leaving directory
        `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile'
        gmake[1]: *** [all-recursive] Error 1
        gmake[1]: Leaving directory
        `/usr/obj/usr/ports/lang/guile/work/guile-2.0.3'
        gmake: *** [all] Error 2
        *** Error code 1

        Stop in /usr/ports/lang/guile.

And indeed if you just go to the libguile directory and execute the
build `guile` file manually, you get a segfault. Here is the backtrace:

$ libtool --mode=execute gdb guile guile.core
    GNU gdb 6.1.1 [FreeBSD]
    Copyright 2004 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and
    you are
    welcome to change it and/or distribute copies of it under certain
    conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for
    details.
    This GDB was configured as "amd64-marcel-freebsd"...(no debugging
    symbols found)...
    Core was generated by `guile'.
    Program terminated with signal 11, Segmentation fault.
    Reading symbols from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25...(no
    debugging symbols found)...done.
    Loaded symbols for
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    Reading symbols from /usr/local/lib/libgc-threaded.so.1...(no
    debugging symbols found)...done.
    Loaded symbols for /usr/local/lib/libgc-threaded.so.1
    Reading symbols from /usr/local/lib/libffi.so.5...done.
    Loaded symbols for /usr/local/lib/libffi.so.5
    Reading symbols from /usr/local/lib/libintl.so.9...done.
    Loaded symbols for /usr/local/lib/libintl.so.9
    Reading symbols from /usr/local/lib/libunistring.so.1...done.
    Loaded symbols for /usr/local/lib/libunistring.so.1
    Reading symbols from /usr/local/lib/libiconv.so.3...done.
    Loaded symbols for /usr/local/lib/libiconv.so.3
    Reading symbols from /usr/local/lib/libgmp.so.10...done.
    Loaded symbols for /usr/local/lib/libgmp.so.10
    Reading symbols from /usr/local/lib/libltdl.so.7...done.
    Loaded symbols for /usr/local/lib/libltdl.so.7
    Reading symbols from /lib/libcrypt.so.5...done.
    Loaded symbols for /lib/libcrypt.so.5
    Reading symbols from /lib/libm.so.5...done.
    Loaded symbols for /lib/libm.so.5
    Reading symbols from /lib/libthr.so.3...done.
    Loaded symbols for /lib/libthr.so.3
    Reading symbols from /lib/libc.so.7...done.
    Loaded symbols for /lib/libc.so.7
    Reading symbols from /libexec/ld-elf.so.1...done.
    Loaded symbols for /libexec/ld-elf.so.1
    #0  0x000000080091f8a5 in scm_c_vm_run () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    [New Thread 802807400 (LWP 104574/guile)]
    (gdb) bt
    #0  0x000000080091f8a5 in scm_c_vm_run () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #1  0x0000000800895e17 in scm_async_click () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #2  0x00000008008f952f in scm_make_smob_type () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #3  0x0000000800890f42 in scm_init_arbiters () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #4  0x00000008008c72c5 in scm_i_init_guile () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #5  0x000000080091b094 in scm_i_init_thread_for_guile () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #6  0x000000080091b0f7 in with_guile_and_parent () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #7  0x0000000800bd3805 in GC_call_with_stack_base () from
    /usr/local/lib/libgc-threaded.so.1
    #8  0x000000080091af81 in scm_i_with_guile_and_parent () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #9  0x00000008008c7135 in scm_boot_guile () from
    /usr/obj/usr/ports/lang/guile/work/guile-2.0.3/libguile/.libs/libguile-2.0.so.25
    #10 0x0000000000400af0 in main ()
    (gdb) 

Finally, here are the patches currently being applied to the guile 3.0.2
tarball before running autoconf/autoheader/configure.

----- files/patch-configure.ac -----
--- ./configure.ac.orig 2011-10-07 19:49:48.000000000 -0400
+++ ./configure.ac      2011-12-06 09:35:02.484201526 -0500
@@ -657,7 +657,7 @@
 #
 AC_CHECK_HEADERS([complex.h fenv.h io.h libc.h limits.h malloc.h
 memory.h process.h string.h \
 regex.h rxposix.h rx/rxposix.h sys/dir.h sys/ioctl.h sys/select.h \
-sys/time.h sys/timeb.h sys/times.h sys/stdtypes.h sys/types.h \
+sys/time.h sys/times.h sys/stdtypes.h sys/types.h \
 sys/utime.h time.h unistd.h utime.h pwd.h grp.h sys/utsname.h \
 direct.h langinfo.h nl_types.h machine/fpu.h poll.h sched.h])
 
@@ -775,6 +775,7 @@
 #   sys/param.h - not in mingw
 #   pthread.h - only available with pthreads.  ACX_PTHREAD doesn't
 #       check this specifically, we need it for the timespec test
 below.
+#   pthread_np.h - available on FreeBSD
 #   sethostname - the function itself check because it's not in mingw,
 #       the DECL is checked because Solaris 10 doens't have in any
 header
 #   hstrerror - on Tru64 5.1b the symbol is available in libc but the
@@ -782,7 +783,7 @@
 #   cuserid - on Tru64 5.1b the declaration is documented to be
 available
 #       only with `_XOPEN_SOURCE' or some such.
 #
-AC_CHECK_HEADERS([crypt.h netdb.h pthread.h sys/param.h sys/resource.h
sys/file.h sys/mman.h])
+AC_CHECK_HEADERS([crypt.h netdb.h pthread.h pthread_np.h sys/param.h
sys/resource.h sys/file.h sys/mman.h])
 AC_CHECK_FUNCS(chroot flock getlogin cuserid getpriority setpriority
 getpass sethostname gethostname)
 AC_CHECK_DECLS([sethostname, hstrerror, cuserid])
 
@@ -1253,7 +1254,7 @@
 # Boehm's GC library
 #
 #--------------------------------------------------------------------
-PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
+PKG_CHECK_MODULES([BDW_GC], [bdw-gc-threaded])
 
 save_LIBS="$LIBS"
 LIBS="$BDW_GC_LIBS $LIBS"
@@ -1364,9 +1365,11 @@
     #         all; not present on MacOS X or Solaris 10
     #     pthread_get_stackaddr_np - "np" meaning "non portable" says
     it
     #         all; specific to MacOS X
+    #     pthread_attr_get_np - "np" meaning "non portable" says it
+    #         all; specific to FreeBSD
     #     pthread_sigmask - not available on mingw
     #
-    AC_CHECK_FUNCS(pthread_attr_getstack pthread_getattr_np
pthread_get_stackaddr_np pthread_sigmask)
+    AC_CHECK_FUNCS(pthread_attr_getstack pthread_getattr_np
pthread_get_stackaddr_np pthread_attr_get_np pthread_sigmask)
 
     # On past versions of Solaris, believe 8 through 10 at least, you
     # had to write "pthread_once_t foo = { PTHREAD_ONCE_INIT };".
@@ -1381,7 +1384,7 @@
     if test "$GCC" = "yes"; then
       # Since GCC only issues a warning for missing braces, so we need
       # `-Werror' to catch it.
-      CFLAGS="-Werror -Wmissing-braces $CFLAGS"
+      CFLAGS="-Wmissing-braces $CFLAGS"
     fi
 
     AC_CACHE_CHECK([whether PTHREAD_ONCE_INIT needs braces],
@@ -1544,7 +1547,7 @@
     # not be "warning free"
     if test "${GUILE_ERROR_ON_WARNING}" = yes
     then
-       POTENTIAL_GCC_CFLAGS="${POTENTIAL_GCC_CFLAGS} -Werror"
+       POTENTIAL_GCC_CFLAGS="${POTENTIAL_GCC_CFLAGS}"
 	enable_compile_warnings=no
     fi
 
----- files/patch-libguile___scm.h -----
--- libguile/__scm.h    2008-02-23 18:14:28.106264450 -0600
+++ libguile/__scm.h    2008-02-23 18:15:41.306005478 -0600
@@ -411,7 +411,8 @@
  * that all the state of the process is contained in the stack.
  */
 
-#if defined (sparc) || defined (__sparc__) || defined (__sparc)
+#if (defined (sparc) || defined (__sparc__) || defined (__sparc)) && \
+    (!defined(__FreeBSD__))
 # define SCM_FLUSH_REGISTER_WINDOWS asm("ta 3")
 #else
 # define SCM_FLUSH_REGISTER_WINDOWS /* empty */
----- files/patch-libguile_gen-scmconfig.c -----
--- libguile/gen-scmconfig.c    2008-02-23 21:38:39.310330888 -0600
+++ libguile/gen-scmconfig.c    2008-02-23 21:39:32.909873567 -0600
@@ -123,6 +123,7 @@
 
 #include "gen-scmconfig.h"
 
+#define _ANSI_SOURCE
 #include <stdio.h>
 #include <string.h>
 
----- files/patch-libguile_numbers.c -----
--- ./libguile/numbers.c.orig   2011-10-10 16:24:38.000000000 -0400
+++ ./libguile/numbers.c        2011-12-06 05:26:45.391199972 -0500
@@ -148,7 +148,7 @@

 #if defined (GUILE_I)
-#if defined HAVE_COMPLEX_DOUBLE
+#if defined HAVE_COMPLEX_DOUBLE && (defined HAVE_CLOG || defined
HAVE_CLOG10 || defined HAVE_CEXP || defined HAVE_USABLE_CSQRT) &&
defined (SCM_COMPLEX_VALUE) 
 
 /* For an SCM object Z which is a complex number (ie. satisfies
    SCM_COMPLEXP), return its value as a C level "complex double". */
----- files/patch-libguile_pthread-threads.h -----
--- libguile/pthread-threads.h  2008-02-27 10:31:41.564950412 -0600
+++ libguile/pthread-threads.h  2008-02-27 10:36:08.383652510 -0600
@@ -26,6 +26,9 @@
 */
 
 #include <pthread.h>
+#if HAVE_PTHREAD_NP_H
+# include <pthread_np.h>
+#endif
 #include <sched.h>
 
 /* Threads 
----- files/patch-libguile_threads.c -----
--- ./libguile/threads.c.orig   2011-10-07 19:49:48.000000000 -0400
+++ ./libguile/threads.c        2011-12-06 05:29:36.754202532 -0500
@@ -120,8 +120,15 @@
   void *start, *end;
   size_t size;
 
+#if HAVE_PTHREAD_ATTR_GET_NP
+  pthread_attr_init (&attr);
+  pthread_attr_get_np (pthread_self (), &attr);
+  pthread_attr_getstack (&attr, &start, &size);
+  pthread_attr_destroy (&attr);
+#elif HAVE_PTHREAD_GETATTR_NP
   pthread_getattr_np (pthread_self (), &attr);
   pthread_attr_getstack (&attr, &start, &size);
+#endif
   end = (char *)start + size;
 
 #if SCM_STACK_GROWS_UP
@@ -2200,6 +2207,20 @@
   return (void *) ctx->uc_mcontext.sc_ar_bsp;
 }
 # endif /* linux */
+# ifdef __FreeBSD__
+#  include <ucontext.h>
+void *
+scm_ia64_register_backing_store_base (void)
+{
+  return (void *)0x8000000000000000;
+}
+void *
+scm_ia64_ar_bsp (const void *opaque)
+{
+  const ucontext_t *ctx = opaque;
+  return (void *)(ctx->uc_mcontext.mc_special.bspstore +
ctx->uc_mcontext.mc_special.ndirty);
+}
+# endif /* __FreeBSD__ */
 #endif /* __ia64__ */

-- 
[email-masked]