[
https://issues.apache.org/activemq/browse/AMQCPP-327?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Kevin Quick reopened AMQCPP-327:
--------------------------------
Fair deuce on the need for the shutdownLibrary() call.
I do disagree on the requirement for shutdown before exit from main... the
example is valid C++ and can be considered to be a useful method of resource
management (see Chapter 3, "Effective C++" by Scott Meyers)... one which I've
used with many other libraries without issues.
I may have been too trivial in my original example; I'll provide an enhanced
version representing a long-running server which performs a shutdown on Ctrl-C.
With the exception of this AMQCPP issue, the shutdown is otherwise ordered and
managed.
I would like to point out as well that the current AMQCPP implementation
precludes linking with any other libraries using the apr, and especially if
they do so in the same manner as AMQCPP, so it's one of the potential issues we
are evaluating in whether or not to use AMQCPP.
I don't wish to dictate your design, but if I may suggest a possible solution
to these issues:
* The core problem is that the AMQCPP initialization calls
decaf::lang::Runtime::initializeRuntime(), which in turn calls a classic
Singleton to obtain a DecafRuntime object whose initializer calls
apr_initialize(). The corresponding ~DecafRuntime calls apr_terminate() and is
invoked when the singleton object goes out of scope (a similar technique to the
auto_ptr in my example, actually).
I would suggest having getRuntime return a decaf Pointer to a new'ed static
global, and furthermore having initializeRuntime return this to ActiveMQCPP
which would store it internally. Each object then returned by an ActiveMQCPP
call (e.g. createCMSConnectionFactory(), createConnection(), etc.) would get a
copy of this Pointer.
By using this technique you would be able to ensure that the ~DecafRuntime()
wasn't called until all the Pointer references were released, which would solve
the shutdown ordering problem.
* I would also then recommend adding a boolean flag parameter (defaulting to
false) to ActiveMQCPP::initializeLibrary() that would pass through to
decaf::Runtime::initializeRuntime() and would indicate to the
initializeRuntime() code that the Pointer should be left as NULL instead of
calling getRuntime(). This flag would be the way for the application to
indicate that it was managing apr initialization/shutdown of apr itself and
that the ActiveMQCPP library should not do this management---which would then
allow the use of other apr-using libraries by that application. The NULL
Pointer is nicely compatible with the above suggestion and requires no
additional work to deactivate apr management by ActiveMQCPP.
I hope you find these suggestions helpful (and apologies if you don't!):
ActiveMQCPP seems to be very nice and useful and I'm just hoping to help with
polishing a few final spots on the finish. If you close this again I promise
not to re-open it.
> SEGFAULT on shutdown with global variable AMQCPP references
> -----------------------------------------------------------
>
> Key: AMQCPP-327
> URL: https://issues.apache.org/activemq/browse/AMQCPP-327
> Project: ActiveMQ C++ Client
> Issue Type: Bug
> Components: CMS Impl
> Affects Versions: 3.2.1
> Environment: CentOS
> Reporter: Kevin Quick
> Assignee: Timothy Bish
> Priority: Minor
> Attachments: mbtest.cpp, mbtest3.cpp
>
>
> If AMQ-CPP resources are managed by global variables and those global
> variables are not explicitly shutdown, the post-exit shutdown code ordering
> usually causes a segfault. This is because the AMQ-CPP internal threads
> shutdown the apr library first and then the global variables attempt to
> close() their connections which result in apr calls.
> A simple program to demonstrate this is attached; when run it results in the
> segfault core trace:
> Program received signal SIGSEGV, Segmentation fault.
> 0xb72f72fe in mutex_hash (mem=0x806089c) at atomic/unix/mutex.c:78
> 78 atomic/unix/mutex.c: No such file or directory.
> in atomic/unix/mutex.c
> (gdb) bt
> #0 0xb72f72fe in mutex_hash (mem=0x806089c) at atomic/unix/mutex.c:78
> #1 0xb72f7457 in apr_atomic_cas32 (mem=0x806089c, with=0, cmp=1) at
> atomic/unix/mutex.c:152
> #2 0xb7e35bca in
> decaf::util::concurrent::atomic::AtomicBoolean::compareAndSet (
> this=0x8060898, expect=true, update=false)
> at decaf/util/concurrent/atomic/AtomicBoolean.cpp:42
> #3 0xb7a51238 in activemq::core::ActiveMQConnection::stop (this=0x8060880)
> at activemq/core/ActiveMQConnection.cpp:425
> #4 0xb7a56ad0 in activemq::core::ActiveMQConnection::close (this=0x8060880)
> at activemq/core/ActiveMQConnection.cpp:355
> #5 0x08048adc in mgr::~mgr() ()
> #6 0x08048b6b in std::auto_ptr<mgr>::~auto_ptr() ()
> #7 0x08048974 in __tcf_1 ()
> #8 0xb7346529 in exit () from /System/Links/Libraries/libc.so.6
> Note: possibly related to AMQCPP-231.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.