[ 
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.

Reply via email to