You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by "Michael J. Kitchin (JIRA)" <ji...@apache.org> on 2008/11/14 20:31:06 UTC
[jira] Created: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Memory leak/segv's with frequent reconnections (identified)
-----------------------------------------------------------
Key: AMQCPP-207
URL: https://issues.apache.org/activemq/browse/AMQCPP-207
Project: ActiveMQ C++ Client
Issue Type: Bug
Components: CMS Impl, Decaf, Openwire
Affects Versions: 2.2.1
Environment: Windows XP, Vistual Studio 2005 (C++)
Reporter: Michael J. Kitchin
Assignee: Timothy Bish
If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
When we shut down our consumer in the following order, as suggested by the sample code:
- delete destination
- delete consumer
- close session
- close connection (*)
- delete session
- delete connection
...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
Thread #1:
> activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
Thread #2:
activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
// Get the number of bytes currently available on the input stream
// that could be read without blocking.
std::size_t available = inputStream->available();
// Calculate the number of bytes that we can read. Always >= 1 byte!
std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
// Read the bytes from the input stream.
int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
This suggests either:
(1) more careful synchronization of the compound stream's state
(2) realigning the compound stream's member data
...I would vote the former, and could suggest some options.
Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
// We have to close the input stream before
// we stop the thread. this will force us to
// wake up the thread if it's stuck in a read
// (which is likely). Otherwise, the join that
// follows will block forever.
if( inputStream != NULL ){
inputStream->close();
inputStream = NULL;
}
// Wait for the thread to die.
if( thread != NULL ){
thread->join();
delete thread;
thread = NULL;
}
// Close the output stream.
if( outputStream != NULL ){
outputStream->close();
outputStream = NULL;
}
...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Timothy Bish (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47395#action_47395 ]
Timothy Bish commented on AMQCPP-207:
-------------------------------------
These issues have been addressed in AMQCPP-200 and will be included in the next release of the library. You can download the trunk code to get access to the fixes.
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Closed: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Michael J. Kitchin (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Michael J. Kitchin closed AMQCPP-207.
-------------------------------------
Resolution: Duplicate
Checked it out, does the trick :) Thanks!
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Issue Comment Edited: (AMQCPP-207) Memory leak/segv's with
frequent reconnections (identified)
Posted by "Michael J. Kitchin (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47397#action_47397 ]
mkitchin edited comment on AMQCPP-207 at 11/14/08 11:56 AM:
----------------------------------------------------------------------
Actually...no. At least the memory leak is probably still there. The inputStream and outputStream members in iotransport are NULL'ed without being deleted. Am I reading this right (code starts at iotransport.cpp:150)?
// We have to close the input stream before
// we stop the thread. this will force us to
// wake up the thread if it's stuck in a read
// (which is likely). Otherwise, the join that
// follows will block forever.
if( inputStream != NULL ){
inputStream->close();
inputStream = NULL;
}
// Wait for the thread to die.
if( thread != NULL ){
thread->join();
delete thread;
thread = NULL;
}
// Close the output stream.
if( outputStream != NULL ){
outputStream->close();
outputStream = NULL;
}
was (Author: mkitchin):
Actually...no. At least the memory leak is probably still there. The inputStream and outputStream members in iotransport are NULL'ed without being deleted. Am I reading this right (code starts at iotransport.cpp:150?
// We have to close the input stream before
// we stop the thread. this will force us to
// wake up the thread if it's stuck in a read
// (which is likely). Otherwise, the join that
// follows will block forever.
if( inputStream != NULL ){
inputStream->close();
inputStream = NULL;
}
// Wait for the thread to die.
if( thread != NULL ){
thread->join();
delete thread;
thread = NULL;
}
// Close the output stream.
if( outputStream != NULL ){
outputStream->close();
outputStream = NULL;
}
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Michael J. Kitchin (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47399#action_47399 ]
Michael J. Kitchin commented on AMQCPP-207:
-------------------------------------------
Alrighty :) I'll set it going and if we're ok at the end of the day I'll close this out.
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Michael J. Kitchin (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47396#action_47396 ]
Michael J. Kitchin commented on AMQCPP-207:
-------------------------------------------
Ahh...ok. I searched the jira but didn't hit on that one. Very well -- thank you for taking the time to comment (and fix the problem), and I'll be sure to get ahold of the latest :) .
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Michael J. Kitchin (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47397#action_47397 ]
Michael J. Kitchin commented on AMQCPP-207:
-------------------------------------------
Actually...no. At least the memory leak is probably still there. The inputStream and outputStream members in iotransport are NULL'ed without being deleted. Am I reading this right (code starts at iotransport.cpp:150?
// We have to close the input stream before
// we stop the thread. this will force us to
// wake up the thread if it's stuck in a read
// (which is likely). Otherwise, the join that
// follows will block forever.
if( inputStream != NULL ){
inputStream->close();
inputStream = NULL;
}
// Wait for the thread to die.
if( thread != NULL ){
thread->join();
delete thread;
thread = NULL;
}
// Close the output stream.
if( outputStream != NULL ){
outputStream->close();
outputStream = NULL;
}
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (AMQCPP-207) Memory leak/segv's with frequent
reconnections (identified)
Posted by "Timothy Bish (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/activemq/browse/AMQCPP-207?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=47398#action_47398 ]
Timothy Bish commented on AMQCPP-207:
-------------------------------------
The stream objects are deleted elsewhere, they are nulled here for completeness. They are not owned by this object.
> Memory leak/segv's with frequent reconnections (identified)
> -----------------------------------------------------------
>
> Key: AMQCPP-207
> URL: https://issues.apache.org/activemq/browse/AMQCPP-207
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl, Decaf, Openwire
> Affects Versions: 2.2.1
> Environment: Windows XP, Vistual Studio 2005 (C++)
> Reporter: Michael J. Kitchin
> Assignee: Timothy Bish
>
> If a CMS consumer client reconnects frequently a segv will arise with reliability (it's guaranteed for us within a hundred reconnections or so). Additionally, in researching this we seem to have stumbled across a related memory leak.
> When we shut down our consumer in the following order, as suggested by the sample code:
> - delete destination
> - delete consumer
> - close session
> - close connection (*)
> - delete session
> - delete connection
> ...a segv will occur at the step marked with a (*), due to effects observable in these thread stack traces:
> Thread #1:
> > activemq-cppd.dll!activemq::transport::IOTransport::close() Line 158 C++
> activemq-cppd.dll!activemq::transport::TransportFilter::close() Line 222 + 0x1b bytes C++
> activemq-cppd.dll!activemq::transport::filters::TcpTransport::close() Line 147 + 0x8 bytes C++
> activemq-cppd.dll!activemq::transport::filters::ResponseCorrelator::close() Line 290 + 0x19 bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormatNegotiator::close() Line 257 + 0x1b bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireConnector::close() Line 178 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::close() Line 89 + 0x19 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::~ActiveMQConnectionData() Line 77 C++
> activemq-cppd.dll!activemq::core::ActiveMQConnectionData::`vector deleting destructor'() + 0x54 bytes C++
> activemq-cppd.dll!activemq::core::ActiveMQConnection::close() Line 160 + 0x37 bytes C++
> Thread #2:
> activemq-cppd.dll!decaf::net::SocketInputStream::read(unsigned char * buffer=0x08b4dcb8, unsigned int offset=0, unsigned int bufferSize=1) Line 170 + 0x18 bytes C++
> > activemq-cppd.dll!decaf::io::BufferedInputStream::bufferData() Line 260 + 0x30 bytes C++
> activemq-cppd.dll!decaf::io::BufferedInputStream::read(unsigned char * targetBuffer=0x0a80f7d8, unsigned int offset=0, unsigned int targetBufferSize=4) Line 181 + 0x8 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readAllData(unsigned char * buffer=0x0a80f7d8, unsigned int length=4) Line 360 + 0x25 bytes C++
> activemq-cppd.dll!decaf::io::DataInputStream::readInt() Line 167 C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireFormat::unmarshal(decaf::io::DataInputStream * dis=0x08bd66d8) Line 227 + 0xf bytes C++
> activemq-cppd.dll!activemq::connector::openwire::OpenWireCommandReader::readCommand() Line 71 + 0x1c bytes C++
> activemq-cppd.dll!activemq::transport::IOTransport::run() Line 188 + 0x15 bytes C++
> activemq-cppd.dll!decaf::lang::Thread::runCallback(apr_thread_t * self=0x08bb3ea0, void * param=0x08bd6828) Line 113 + 0x15 bytes C++
> libapr-1.dll!dummy_worker(void * opaque=0x08bb3ea0) Line 80 C
> ...where, in thread #2, the SocketInputStream interior to the BufferedInputStream (the inputStream member) has been NULL'ed between two method calls shown below, ending at bufferedinputstream.cpp:260:
> // Get the number of bytes currently available on the input stream
> // that could be read without blocking.
> std::size_t available = inputStream->available();
> // Calculate the number of bytes that we can read. Always >= 1 byte!
> std::size_t bytesToRead = max( (std::size_t)1, min( available, getUnusedBytes() ) );
> // Read the bytes from the input stream.
> int bytesRead = inputStream->read( getTail(), 0, bytesToRead );
> ....as a result of the stream close() call in thread #1. The close() call is in place to break any waiting IO so the executor thread may terminate in an orderly fashion, but the stream and/or iotransport calls don't anticipate a case where in-stream processing is underway at the time its internal state is reset.
> This suggests either:
> (1) more careful synchronization of the compound stream's state
> (2) realigning the compound stream's member data
> ...I would vote the former, and could suggest some options.
> Additionally, when reviewing the code in in thread #1 we found the following, beginning at iotransport.cpp:150:
> // We have to close the input stream before
> // we stop the thread. this will force us to
> // wake up the thread if it's stuck in a read
> // (which is likely). Otherwise, the join that
> // follows will block forever.
> if( inputStream != NULL ){
> inputStream->close();
> inputStream = NULL;
> }
> // Wait for the thread to die.
> if( thread != NULL ){
> thread->join();
> delete thread;
> thread = NULL;
> }
> // Close the output stream.
> if( outputStream != NULL ){
> outputStream->close();
> outputStream = NULL;
> }
> ...our familiarity with decaf is limited, but it appears inputStream and outputStream are conventional pointers, so should therefore be deleted prior to being set to NULL to avoid leaking memory. To minimize the other potential segv edge cases, we would suggest doing the close() calls before completing the thread join(), then deleting/NULL'ing the pointers afterwards.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.