Re: BSONObjBuilder decouple

121 views
Skip to first unread message

James

unread,
Nov 13, 2012, 5:37:08 PM11/13/12
to mongod...@googlegroups.com
I was not able to reproduce this running through the decouple operation. Please provide stack trace and more details. Even better would be to share buildable/runnable sample code that reproduces. Thanks!

On Tuesday, November 13, 2012 3:24:21 PM UTC-5, James wrote:
It looks like this should work, given "bldr.obj()" in your working example calls decouple as well to transfer buffer ownership. Can you provide a stack trace for this? I will try to reproduce as well.

On Tuesday, November 13, 2012 12:28:28 PM UTC-5, khanalesb wrote:
I am trying to use BSONObjBuilder as a serializer and decouple to avoid memcopy.

        mongo::BSONObjBuilder bldr;
....................
....................
....................

#ifdef X  
//THIS WORKS
        mongo::BSONObj obj = bldr.obj();
        zmq::message_t replyBody( obj.objsize() );
        std::memcpy( replyBody.data(), obj.objdata(), obj.objsize() );
#else
//SEG FAILT
        int len;
        char* buf = bldr.decouple(len);
        zmq::message_t replyBody( buf, len, zmqFree );
#endif


Do I have to call anything else before decouple? Can I use it at all?
Thanks.

khanalesb

unread,
Nov 14, 2012, 10:55:46 AM11/14/12
to mongod...@googlegroups.com


This works:

        int len;
        char* buf = bldr.decouple(len);
        char* buf1 = (char*) malloc(len);
        memcpy(buf1, buf, len);
        zmq::message_t replyBody( buf1, len, zmqFree );
but it is malloc and memcpy...
In original example:

        int len;
        char* buf = bldr.decouple(len);
        zmq::message_t replyBody( buf, len, zmqFree );
it cores when 0mq calls my clallback to free buffer(zmqFree). All zmqFree does is free...
inline void zmqFree(void* ptr, void* hint) {
    ::free(ptr);
}

khanalesb

unread,
Nov 14, 2012, 11:20:19 AM11/14/12
to mongod...@googlegroups.com


On Tuesday, November 13, 2012 12:28:28 PM UTC-5, khanalesb wrote:
I am trying to use BSONObjBuilder as a serializer and decouple to avoid memcopy.

        mongo::BSONObjBuilder bldr;
....................
....................
....................

#ifdef X  
//THIS WORKS
        mongo::BSONObj obj = bldr.obj();
        zmq::message_t replyBody( obj.objsize() );
        std::memcpy( replyBody.data(), obj.objdata(), obj.objsize() );
#else
//SEG FAILT
        int len;
        char* buf = bldr.decouple(len);
        zmq::message_t replyBody( buf, len, zmqFree );
#endif


Do I have to call anything else before decouple? Can I use it at all?
Thanks.

Stacktrace:
 (gdb) where
#0  0x00007ffff638a8a5 in raise () from /lib64/libc.so.6
#1  0x00007ffff638c085 in abort () from /lib64/libc.so.6
#2  0x00007ffff63c7a37 in __libc_message () from /lib64/libc.so.6
#3  0x00007ffff63cd366 in malloc_printerr () from /lib64/libc.so.6
#4  0x0000000000413b40 in its::hvr::ps::zmqFree (ptr=0x7fffe4017314, hint=0x0) at ../src/CommonDefs.cpp:16
#5  0x00007ffff7b6b0f2 in zmq_msg_close (msg_=0x7fffec0013e0) at zmq.cpp:152
#6  zmq_msg_close (msg_=0x7fffec0013e0) at zmq.cpp:130
#7  0x00007ffff7b52fa5 in zmq::encoder_t::message_ready (this=0x7fffec001398) at encoder.cpp:56
#8  0x00007ffff7b6c914 in get_data (this=0x7fffec0012e0) at encoder.hpp:80
#9  zmq::zmq_engine_t::out_event (this=0x7fffec0012e0) at zmq_engine.cpp:165
#10 0x00007ffff7b5773e in zmq::object_t::process_command (this=0x7fffdc005d10, cmd_=...) at object.cpp:63
#11 0x00007ffff7b546ec in zmq::io_thread_t::in_event (this=0x7391d0) at io_thread.cpp:83
#12 0x00007ffff7b5373e in zmq::epoll_t::loop (this=0x7395c0) at epoll.cpp:161
#13 0x00007ffff7b67566 in thread_routine (arg_=0x739630) at thread.cpp:75
#14 0x00007ffff6142851 in start_thread () from /lib64/libpthread.so.0
#15 0x00007ffff643f67d in clone () from /lib64/libc.so.6

khanalesb

unread,
Nov 14, 2012, 11:29:20 AM11/14/12
to mongod...@googlegroups.com

Wrong builder constructor?
    mongo::BSONObjBuilder bldrReply;
    bldrReply.append( "HasMore", ( src.holdings_.size() > Profile::getInstance().getReplyMsgSize() ) );
    bldrReply.append( "RequestId", src.requestId_ );

    int len;
    char* buf = bldrReply.decouple(len);
    std::cerr << (void*) buf << "\n";
    free(buf);
 This cores on free call!!!!
Should I use different constructor?

James

unread,
Nov 14, 2012, 11:41:47 AM11/14/12
to mongod...@googlegroups.com
I can reproduce now. Thanks for the clarification on crash location. The constructor you are using should be fine. Will debug and get back to you with my findings.

khanalesb

unread,
Nov 14, 2012, 11:56:38 AM11/14/12
to mongod...@googlegroups.com


decouple returns buffer + offset  rather than just buffer !!!!             !!! char *data = _b.buf() + _offset; !!!
How do I get buffer to free ??????
      char* _done() {
            if ( _doneCalled )
                return _b.buf() + _offset;

            _doneCalled = true;
            _s.endField();
            _b.appendNum((char) EOO);
            char *data = _b.buf() + _offset;
            int size = _b.len() - _offset;
            *((int*)data) = size;
            if ( _tracker )
                _tracker->got( size );
            return data;
        }

khanalesb

unread,
Nov 14, 2012, 12:26:44 PM11/14/12
to mongod...@googlegroups.com


On Tuesday, November 13, 2012 12:28:28 PM UTC-5, khanalesb wrote:
I am trying to use BSONObjBuilder as a serializer and decouple to avoid memcopy.

        mongo::BSONObjBuilder bldr;
....................
....................
....................

#ifdef X  
//THIS WORKS
        mongo::BSONObj obj = bldr.obj();
        zmq::message_t replyBody( obj.objsize() );
        std::memcpy( replyBody.data(), obj.objdata(), obj.objsize() );
#else
//SEG FAILT
        int len;
        char* buf = bldr.decouple(len);
        zmq::message_t replyBody( buf, len, zmqFree );
#endif


Do I have to call anything else before decouple? Can I use it at all?
Thanks.

Working version:
    mongo::BufBuilder& bb = bldrReply.bb();
    void* hint = bb.buf();

    int len;
    char* buf = bldrReply.decouple(len);
    zmq::message_t reply( buf, len, zmqFreeHint, hint );
 
Actually call free on buffer from builder - ugly. Better idea?

James

unread,
Nov 15, 2012, 12:29:51 PM11/15/12
to mongod...@googlegroups.com

Your original usage of the decouple method was correct. This is definitely a bug in the implementation of BSONObjBuilder. A ticket has been entered to fix:
https://jira.mongodb.org/browse/SERVER-7671

While waiting on a fix my suggestion would to use your original implementation (with the memcpy) if you can afford to do so or test an alternate solution very carefully. Please track the ticket above for status on the fix.

Thanks for your help in identifying this!

James

khanalesb

unread,
Nov 16, 2012, 12:02:33 AM11/16/12
to mongod...@googlegroups.com
Hmm...
If you do fix - every user is broken. On the other hand in doc/code it says that has to be freed  (::free())
Do you expect to change BufBuilder? Reason not to keep this implementation?

Reply all
Reply to author
Forward
0 new messages