ibm-messaging / mq-golang

Calling IBM MQ from Go applications
Apache License 2.0
168 stars 60 forks source link

Possible issue with Message Handle and GMO on callbacks #93

Closed sasbury closed 5 years ago

sasbury commented 5 years ago

Using the latest version - 5e39ebf

I don't have a small example, but can put one together if you need me to.

I am seeing an issue where the GMO and GMO message handle lose their qmgr pointer during a callback. Once that is lost I can't get to the message properties. I tried printing the structs and both the pointer in the GMO and the Message handle are set to nil, but the other elements are still present.

I am not sure why the pointer to the qMgr is lost, i don't see anything in the copy to/from C.

If I use polling I can use MQGMO_PROPERTIES_IN_HANDLE with a local handle and everything works great. I was thinking callbacks will be better for threading, but maybe go routines polling is ok.

Another options is if there is a way to decode the message properties without setting MQGMO_PROPERTIES_IN_HANDLE but I couldn't find it.

ibmmqmet commented 5 years ago

I don't understand what you mean by "GMO lose their qmgr pointer".

There are callbacks which do not return any message, where the MQCBC.CallType is set to EVENT_CALL. Those can be driven for some error situtations - check the MQRC/MQCC first. Those event callbacks do not have messages (and therefore no message handle).

sasbury commented 5 years ago

The first thing I do is:

if mqErr != nil && mqErr.MQCC != ibmmq.MQCC_OK {
            if mqErr.MQRC == ibmmq.MQRC_NO_MSG_AVAILABLE {

but i do not check the call type, i will give that a shot. I wasn't having any issues until i started trying to use message handles to get properties, but maybe the code just worked by accident.

The "lose their qmgr pointer" refers to the GMO object (passed by pointer) and its message handle. Both have a nil qMgr property on the callback. They do not have a nil value before i register and start the callback.

I will double check the event type but wanted to clear that up as well.

sasbury commented 5 years ago

No luck on the event type, even if i ignore those callbacks i get a panic because the message handle has a nil pointer to the qMgr. The hMsg was set when I printed it, but the qMgr was nil.

ibmmqmet commented 5 years ago

OK - I think I can see what's happening. The message handle is correctly copied from the C layer, but the Go version of that object should also have the qmgr(hConn) added to it. But worse is that the hConn is not otherwise available to the callback function - it's embedded in the queue handle, but inaccessible to application code. So doing an MQDISC or MQCMIT from the callback is not possible, and putting it in the message handle only helps if there IS a message handle. The only good fix is to change the callback function signature to also pass the qMgr object. So I've just created a branch cbmh that has that change. See if it helps before I merge it

sasbury commented 5 years ago

I will give it a shot

sasbury commented 5 years ago

branch (cbmh) looks good to me. I am a bit worried about changing the signature, but if you think it is ok, I am good with it. I don't actually need that qmgr in the callback since I keep it in a closure, but I definitely need the message handle to carry it through.

Thanks for the quick fix (especially without example code which I felt bad for not providing).