Question

I'm trying to use BDB in a simple program, but I'm running into a segfault issue.

Program received signal SIGSEGV, Segmentation fault.
__bamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/btree/bt_cursor.c:2077
2077    ../src/btree/bt_cursor.c: No such file or directory.

gdb backtrace:

#0  __bamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/btree/bt_cursor.c:2077
#1  0x0000000000404152 in bzing_inv_add (hnd=0x60c010, hash=..., data=80)
    at /atlas/www/libbzing/src/bzing.c:189
#2  0x00000000004041fa in bzing_block_add (hnd=0x60c010, 
    data=0x7fffb0d7d000 "\001", max_len=1163428803, actual_len=0x7fffffffe458)
    at /atlas/www/libbzing/src/bzing.c:217
#3  0x00000000004044d4 in bzing_index_regen (hnd=0x60c010, 
    data=0x7fffb0d7d000 "\001", len=1163428803)
    at /atlas/www/libbzing/src/bzing.c:269
#4  0x000000000040301c in main (argc=1, argv=0x7fffffffe628)
    at /atlas/www/libbzing/test/bzing_test.c:75

When running with valgrind memcheck the segfault disappears and the program completes normally without any warnings from valgrind.

Note how according to gdb the __bamc_put is passed a NULL pointer as the key parameter. This seems like the obvious culprit for causing the segfault. But here's the thing, the second parameter for DB->put is actually supposed to be the the transaction or NULL for a non-transaction insert.

Here's my code:

DBT bdb_key, bdb_data;

memset(&bdb_key, 0, sizeof(DBT));
memset(&bdb_data, 0, sizeof(DBT));
bdb_key.data = hash.d8;
bdb_key.size = 32;
bdb_data.data = (char *) &data;
bdb_data.size = 8;

result = hnd->bdb_inv->put(hnd->bdb_inv, NULL, &bdb_key, &bdb_data, 0);

From: https://github.com/justmoon/bzing/blob/master/src/bzing.c

This is the signature as it appears in the documentation and in all examples that I've found.

DB->put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags);

See http://docs.oracle.com/cd/E17076_02/html/api_reference/C/dbput.html

If I try to use the signature that gdb indicates (omitting the DB_TXN parameter) I just get compiler warnings as the compiler uses the correct signature as per the documentation.

So I thought maybe I'm linking against the wrong library? But:

$ ldd build/test/bzing_test | grep libdb
    libdb-5.1.so => /usr/lib/x86_64-linux-gnu/libdb-5.1.so (0x00007f28dd7ec000)
$ dpkg -L libdb5.1-dev
/.
/usr
/usr/share
/usr/share/doc
/usr/include
/usr/include/db.h
/usr/include/db_185.h
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libdb-5.1.a
/usr/share/doc/libdb5.1-dev
/usr/lib/x86_64-linux-gnu/libdb.a
/usr/lib/x86_64-linux-gnu/libdb.so
$ dpkg -L libdb5.1
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libdb5.1
/usr/share/doc/libdb5.1/build_signature_amd64.txt
/usr/share/doc/libdb5.1/copyright
/usr/share/doc/libdb5.1/changelog.Debian.gz
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libdb5.1
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libdb-5.1.so

The compiler is definitely using /usr/include/db.h and both the header and library are the original files from the Ubuntu packages. I first ran into the problem on Ubuntu 11.10 and it persisted after upgrading to Ubuntu 12.04.

I'm compiling with CMake and these flags:

cd /atlas/www/libbzing/build/src && /usr/bin/gcc  -DBZING_BUILD -Wall -fvisibility=hidden -std=c99 -pedantic -DDEBUG -g -I/atlas/www/libbzing/build/src/../bzing-0.1.0/include/bzing/..    -o CMakeFiles/bzing_s.dir/bzing.c.o   -c /atlas/www/libbzing/src/bzing.c
...
/usr/bin/ar cr ../bzing-0.1.0/lib/libbzing_s.a  CMakeFiles/bzing_s.dir/bzing.c.o CMakeFiles/bzing_s.dir/bzing_parser.c.o CMakeFiles/bzing_s.dir/util.c.o
/usr/bin/ranlib ../bzing-0.1.0/lib/libbzing_s.a
...
/usr/bin/gcc   -Wall -fvisibility=hidden -std=c99 -pedantic -DDEBUG -g    CMakeFiles/bzing_test.dir/bzing_test.c.o  -o bzing_test -rdynamic -L/atlas/www/libbzing/build/test/../bzing-0.1.0/lib ../bzing-0.1.0/lib/libbzing_s.a -llmc -lpthread -lrt -lcrypto -ltokyocabinet -ldb -Wl,-rpath,/atlas/www/libbzing/build/test/../bzing-0.1.0/lib

If I run the same program, but select the hash table database type, I get the same problem with __hamc_put instead:

Program received signal SIGSEGV, Segmentation fault.
__hamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/hash/hash.c:1068

I tried -fPIC, but got the same result.

Any help would be very much appreciated. Maybe I'm on the wrong track and and gdb is just showing the wrong signature for some reason, but the problem is elsewhere?

Update:

It looks like the ->put pointer is wrong. It should point to __db_put_pp:

dbp->put = __db_put_pp;

(db_method.c line 248)

But points to __bamc_put/__hamc_put instead:

Breakpoint 3, bzing_inv_add (hnd=0x60c010, hash=..., data=80)
    at /atlas/www/libbzing/src/bzing.c:189
189     result = hnd->bdb_inv->put(hnd->bdb_inv, NULL, &bdb_key, &bdb_data, 0);
(gdb) print hnd->bdb_inv->put
$1 = (int (*)(DB *, DB_TXN *, DBT *, DBT *, 
    u_int32_t)) 0x7ffff7034d00 <__hamc_put>
Was it helpful?

Solution

The "missing" parameter is because by the time you get to __bamc_put (or __hamc_put), the transaction has been moved into the dbc parameter. (This is a "DB cursor".) What I don't quite get is why there's no frame above __bamc_put, since it's called through another layer (actually two: __db_put_pp and then __db_put).

It's especially weird that it would work with valgrind, and fail without it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top