0.94.14 problems on Debian/sparc

Matthias Andree matthias.andree at gmx.de
Fri Jun 10 10:16:37 CEST 2005


On Thu, 09 Jun 2005, Clint Adams wrote:

> Program terminated with signal 10, Bus error.
...
> #0  0x00013d60 in convert_external_to_internal (dsh=0x360f8, ex_data=0xeffff608, in_data=0xeffff588) at ../../src/datastore.c:106
> 	i = 3072
> 	cv = (uint32_t *) 0x36779
> #1  0x000143c0 in ds_hook (ex_key=0xeffff610, ex_data=0xeffff608, userdata=0xeffff7a0) at ../../src/datastore.c:348
> 	ret = 221432
> 	w_key = {leng = 9, text = 0x36108 "yours-340"}
> 	in_data = {count = {0, 0}, date = 0}
> 	dsh = (dsh_t *) 0x360f8
> #2  0x00017760 in tdb_traversor (tdb_handle=0x36218, key={dptr = 0x36770 "yours-340", dsize = 9}, data={dptr = 0x36779 "", dsize = 12}, userdata=0xeffff730) at ../../src/datastore_tdb.c:283
> 	rc = 221720
> 	dbv_key = {data = 0x36108, leng = 9}
> 	dbv_data = {data = 0x36779, leng = 12}
> #3  0x7002f9dc in tdb_traverse () from /usr/lib/libtdb.so.1
> No symbol table info available.

Now that explains everything. dbv_data is passed on to ds_hook, where
the convert_external_to_internal performs a word-sized access (word is
32 bits), and dbv_data is unaligned. SPARC and m68k and some other
architectures do not support unaligned word access and cause the SIGBUS,
other machines that support unaligned access get awfully slow.

Try this patch:

Index: datastore_tdb.c
===================================================================
RCS file: /cvsroot/bogofilter/bogofilter/src/datastore_tdb.c,v
retrieving revision 1.51.22.1
diff -u -r1.51.22.1 datastore_tdb.c
--- datastore_tdb.c	31 May 2005 15:04:05 -0000	1.51.22.1
+++ datastore_tdb.c	10 Jun 2005 08:15:03 -0000
@@ -268,20 +268,34 @@
     dbv_t dbv_key, dbv_data;
     userdata_t *hookdata = userdata;
 
-    /* Question: Is there a way to avoid using malloc/free? */
-
-    /* switch to "dbv_t *" variables */
+    /* TDB happily returns data from odd addresses, so we need to
+     * memcpy() everything to properly aligned storage (malloc() is
+     * fine) if our callee wishes to perform word-sized access - without
+     * memcpy(), the callee will die with SIGBUS (SPARC, m68k) or get
+     * extremely slow (i386). */
+
+    /* XXX FIXME: Possible optimization if this function is only used by
+     * one caller at a time (i. e. no threads): allocate buffers
+     * statically and reuse them as long as they are of sufficient size
+     * and reallocate otherwise. */
+
+    /* copy key */
+    /* XXX FIXME: do we really need to use C-string compatible keys?
+     * Looks wasteful. */
     dbv_key.leng = key.dsize;
     dbv_key.data = xmalloc(dbv_key.leng+1);
     memcpy(dbv_key.data, key.dptr, dbv_key.leng);
     ((char *)dbv_key.data)[dbv_key.leng] = '\0';
 
-    dbv_data.data = data.dptr;
-    dbv_data.leng = data.dsize;		/* read count */
+    /* copy data */
+    dbv_data.leng = data.dsize;
+    dbv_data.data = xmalloc(dbv_data.leng);
+    memcpy(dbv_data.data, data.dptr, dbv_data.leng);
 
     /* call user function */
     rc = hookdata->hook(&dbv_key, &dbv_data, hookdata->userdata);
 
+    xfree(dbv_data.data);
     xfree(dbv_key.data);
 
     return rc;

-- 
Matthias Andree



More information about the bogofilter-dev mailing list