You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by "Aaron Riekenberg (JIRA)" <ji...@apache.org> on 2008/05/27 18:56:55 UTC

[jira] Commented: (AMQCPP-178) Core dump in ActiveMQException::buildMessage

    [ https://issues.apache.org/activemq/browse/AMQCPP-178?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=43048#action_43048 ] 

Aaron Riekenberg commented on AMQCPP-178:
-----------------------------------------

I tried building activemq-cpp-2.1.3 on a 32-bit x86 linux machine and was unable to reproduce the failure.  The failure only seems to happen on 64-bit amd64.

Google turns up various bug reports where multiple uses of vsnprintf without va_copy crashes on amd64 but not on x86.  Apparently there are some differences in the implementations that require correct use of va_copy on amd64.  At any rate using va_copy and only making one vsnprintf per va_start/va_end pair is correct on all architectures.

Some links to similar problems:

http://lists.freedesktop.org/archives/xorg-bugzilla-noise/2004-March/000004.html
http://mlblog.osdir.com/redhat.amd64/2006-12/index.shtml

> Core dump in ActiveMQException::buildMessage
> --------------------------------------------
>
>                 Key: AMQCPP-178
>                 URL: https://issues.apache.org/activemq/browse/AMQCPP-178
>             Project: ActiveMQ C++ Client
>          Issue Type: Bug
>          Components: CMS Impl
>    Affects Versions: 2.1.3
>         Environment: Ubuntu 8.0.4 AMD64, ActiveMQ 5.1.0 running inside JBoss 4.2.2, ActiveMQ-CPP 2.1.3
>            Reporter: Aaron Riekenberg
>            Assignee: Nathan Mittler
>
> Running the "example" example program, I find I get a segmentation fault in "example" if I terminate the message broker while its running.  This seems like quite a serious problem, I can't have all c++ clients core dump if the broker goes down.  Full stack trace from gdb is at the bottom.
> Did some digging with gdb and found the "size" variable in ActiveMQException::buildMessage is 256, meaning our string was longer than 128 so we're going through the loop for the second time:
> (gdb) down
> #3  0x00007fd6a575d90f in activemq::exceptions::ActiveMQException::buildMessage (
>     this=0x610600, 
>     format=0x7fd6a5898218 "No valid response received for command: %s, check broker.", 
>     vargs=<value optimized out>) at activemq/exceptions/ActiveMQException.cpp:75
> 75              int written = vsnprintf(buffer, size, format, vargs);
> (gdb) p size
> $1 = 256
> ActiveMQException::buildMessage does a vsnprintf to try to write vargs into buffer, and if buffer isn't big enough it doubles the size and tries another vsnprintf.  Trouble is it's only legal to do ONE vsnprintf between calls to va_start and va_end, so on the second try vargs is garbage.  See "man vsnprintf":
>        The  functions  vprintf(),  vfprintf(),  vsprintf(), vsnprintf() are equivalent to the
>        functions printf(), fprintf(), sprintf(), snprintf(), respectively, except  that  they
>        are  called with a va_list instead of a variable number of arguments.  These functions
>        do not call the va_end macro.  Because they invoke the va_arg macro, the value  of  ap
>        is undefined after the call.  See stdarg(3).
> One possible solution is to use va_copy or __va_copy to make a copy of vargs so we have a fresh copy to traverse on each iteration in buildMessage.  I've verified the following works on my system (I have __va_copy instead of va_copy on Ubunutu 8.0.4):
> void ActiveMQException::buildMessage(const char* format, va_list& vargs)
> {
>     // Allocate buffer with a guess of it's size
>     int size = 128;
>     // Format string
>     while( true ){
>         // Allocate a buffer of the specified size.
>         char* buffer = new char[size];
>         va_list vargsCopy;
>         __va_copy(vargsCopy, vargs);
>         int written = vsnprintf(buffer, size, format, vargsCopy);
>         if (written > -1 && written < size-1) {
>             // Guessed size was enough. Assign the string.
>             message.assign (buffer, written);
>             // assign isn't passing ownership, just copying, delete
>             // the allocated buffer.
>             delete [] buffer;
>             va_end(vargsCopy);
>             break;
>         }
>         // Our buffer wasn't big enough - destroy the old buffer,
>         // double the size and try again.
>         delete [] buffer;
>         va_end(vargsCopy);
>         size *= 2;
>     }
>     //activemq::logger::SimpleLogger logger("com.yadda1");
>     //logger.log( message );   
> }
> Full stack trace of the failure from gdb:
> Core was generated by `/home/aaron/activemq/activemq-cpp-2.1.3-src/src/examples/.libs/lt-example
> '.
> Program terminated with signal 11, Segmentation fault.
> [New process 22513]
> [New process 22517]
> [New process 22497]
> #0  0x00007fd6a4b7c060 in strlen () from /lib/libc.so.6
> (gdb) where
> #0  0x00007fd6a4b7c060 in strlen () from /lib/libc.so.6
> #1  0x00007fd6a4b48e1a in vfprintf () from /lib/libc.so.6
> #2  0x00007fd6a4b6c9ea in vsnprintf () from /lib/libc.so.6
> #3  0x00007fd6a575d90f in activemq::exceptions::ActiveMQException::buildMessage (
>     this=0x610600, 
>     format=0x7fd6a5898218 "No valid response received for command: %s, check broker.", 
>     vargs=<value optimized out>) at activemq/exceptions/ActiveMQException.cpp:75
> #4  0x00007fd6a57709e8 in CommandIOException (this=0x610600, 
>     file=0x7fd6a58981e0 "activemq/transport/filters/ResponseCorrelator.cpp", lineNumber=145, 
>     msg=0x7fd6a5898218 "No valid response received for command: %s, check broker.")
>     at ./activemq/transport/CommandIOException.h:67
> #5  0x00007fd6a57c20d8 in activemq::transport::filters::ResponseCorrelator::request (
>     this=<value optimized out>, command=<value optimized out>)
>     at activemq/transport/filters/ResponseCorrelator.cpp:147
> #6  0x00007fd6a5796735 in activemq::connector::openwire::OpenWireFormatNegotiator::request (
>     this=0x60ef60, command=0x610688)
>     at activemq/connector/openwire/OpenWireFormatNegotiator.cpp:102
> #7  0x00007fd6a57991fa in activemq::connector::openwire::OpenWireConnector::syncRequest (
>     this=<value optimized out>, command=0x7fd6a5898240)
>     at activemq/connector/openwire/OpenWireConnector.cpp:1349
> #8  0x00007fd6a5799dd1 in activemq::connector::openwire::OpenWireConnector::send (
>     this=0x60d5c0, message=<value optimized out>, producerInfo=<value optimized out>)
>     at activemq/connector/openwire/OpenWireConnector.cpp:838
> #9  0x00007fd6a5735aec in activemq::core::ActiveMQSession::send (this=<value optimized out>, 
>     message=0x610680, producer=0x6103d0) at activemq/core/ActiveMQSession.cpp:673
> #10 0x00007fd6a5741b00 in activemq::core::ActiveMQProducer::send (this=0x6103d0, 
>     destination=<value optimized out>, message=0x610680, deliveryMode=626508689, priority=4, 
>     timeToLive=0) at activemq/core/ActiveMQProducer.cpp:192
> #11 0x00007fd6a574161a in activemq::core::ActiveMQProducer::send (this=0x6554514d65766974, 
>     destination=0x7fd6a5898240, message=0x409a2958) at activemq/core/ActiveMQProducer.cpp:147
> #12 0x00007fd6a574193b in activemq::core::ActiveMQProducer::send (this=0x6103d0, 
>     message=0x610680) at activemq/core/ActiveMQProducer.cpp:106
> #13 0x0000000000402bbe in HelloWorldProducer::run (this=0x7fffadd50ff0) at main.cpp:114
> #14 0x00007fd6a575bda0 in activemq::concurrent::Thread::runCallback (
>     param=<value optimized out>) at activemq/concurrent/Thread.cpp:152
> #15 0x00007fd6a48eb3f7 in start_thread () from /lib/libpthread.so.0
> #16 0x00007fd6a4bd8b2d in clone () from /lib/libc.so.6
> #17 0x0000000000000000 in ?? ()

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.