On Thu, 2017-03-09 at 02:06 -0700, Tobias Duckworth wrote: > I got to the bottom of this problem. > > The problem is to to with the lifetime of the proton::delivery > object. > > In a connection_engine build, the IO is asynchronous to the > proton::handler > interface, and therefore this problem may only occur in > connection_engine > builds (not absolutely certain, as I've not tested on a 'normal' > build). > > When a message is received, it comes along with a delivery object. > The > delivery object can be used to accept, reject, release the delivery > with the > broker. > > Internally to the proton-c C implementation there are a complicated > set of > state transitions that happen which I have not totally got my head > around. > However, what I do know is that the delivery object needs to stick > around > until the operation is totally finished - Otherwise it's possible for > the > observed behaviour to happen, which causes the assertion failures or > a much > nastier crash. > > The call to proton::delivery::accept (or release, reject) returns > almost > straightaway, and then the actual work of settling the message with > the > broker happens when the underlying IO operation is invoked with > process(), > or process_nothrow(). If, by this time, the delivery object that was > used > has been deleted or destroyed, then the problem will happen > > Turning on tracing using PN_TRACE_FRM, one can see the following when > the > engine has finished with the delivery: > > [0x2b4af8030500]:1 -> @disposition(21) [role=true, first=124, > last=124, > settled=true, state=@accepted(36) []] . > > Unfortunately, there is no interface back to the C++ world to tell us > when > the delivery is finished with, and so there appears to be no way to > know > when it is safe to destroy the delivery object. >
There are callbacks, but on the sender side the delivery is referred to as a "tracker", "delivery" is only used on the receiver side. This is an attempt to rationalize the API since there are different ops relevant on sender and receiver side. > Other than keeping proton::delivery objects sticking around in memory > forever (which does solve the problem, but is not an option), does > anyone > have any ideas for solving this? > > It seems to me like the C++ proton::delivery object itself should > know about > whether it has been settled with the broker or not, so unless anyone > has a > better suggestion this is likely to be what I will add. > They should be deleted automatically without user intervention after they settle and all events are processed. If you have a reproducer to show they are not then raise a JIRA (even better if you attach a fix :). Note that unsettled deliveries will outlive the link they were created on, the AMQP spec allows settlement after the link has closed. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
