Skip to content

Commit faf1610

Browse files
authored
Merge pull request #76 from ibm-messaging/client-cb
Client cb
2 parents d87272d + eb8f640 commit faf1610

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## January 24 2019
4+
* Deal with callback functions being called unexpectedly (#75)
5+
36
## January 2019
47
* mqmetric - Add some configuration validation
58
* mqmetric - Make it possible to use CAPEXPRY for statistics subscriptions

ibmmq/mqicb.go

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,24 @@ accessible from a C function. See mqicb_c.go for the proxy/gateway C function th
6363
//export MQCALLBACK_Go
6464
func MQCALLBACK_Go(hConn C.MQHCONN, mqmd *C.MQMD, mqgmo *C.MQGMO, mqBuffer C.PMQVOID, mqcbc *C.MQCBC) {
6565

66+
var cbHObj *MQObject
67+
6668
// Find the real callback function and invoke it
6769
// Invoked function should match signature of the MQCB_FUNCTION type
6870
gogmo := NewMQGMO()
6971
gomd := NewMQMD()
7072
gocbc := NewMQCBC()
7173

72-
copyGMOfromC(mqgmo, gogmo)
73-
copyMDfromC(mqmd, gomd)
74+
// For EVENT callbacks, the GMO and MD may be NULL
75+
if mqgmo != (C.PMQGMO)(C.NULL) {
76+
copyGMOfromC(mqgmo, gogmo)
77+
}
78+
79+
if mqmd != (C.PMQMD)(C.NULL) {
80+
copyMDfromC(mqmd, gomd)
81+
}
82+
83+
// This should never be NULL
7484
copyCBCfromC(mqcbc, gocbc)
7585

7686
mqreturn := &MQReturn{MQCC: int32(mqcbc.CompCode),
@@ -79,16 +89,44 @@ func MQCALLBACK_Go(hConn C.MQHCONN, mqmd *C.MQMD, mqgmo *C.MQGMO, mqBuffer C.PMQ
7989
}
8090

8191
key := makeKey(hConn, mqcbc.Hobj)
82-
if info, ok := cbMap[key]; ok {
92+
info, ok := cbMap[key]
93+
94+
// The MQ Client libraries seem to sometimes call us with an EVENT
95+
// even if it's not been registered. And therefore the cbMap does not
96+
// contain a matching callback function with the hObj. It has
97+
// been seen with a 2033 return (see issue #75).
98+
//
99+
// This feels like wrong behaviour from the client, but we need to find a
100+
// way to deal with it even if it gets fixed in future.
101+
// The way I've chosen is to find the first entry in
102+
// the map associated with the hConn and call its registered function with
103+
// a dummy hObj.
104+
if !ok {
105+
if gocbc.CallType == MQCBCT_EVENT_CALL && mqcbc.Hobj == 0 {
106+
key = makePartialKey(hConn)
107+
for k, i := range cbMap {
108+
if strings.HasPrefix(k, key) {
109+
ok = true
110+
info = i
111+
cbHObj = &MQObject{qMgr: info.hObj.qMgr, Name: ""}
112+
// Only care about finding one match in the table
113+
break
114+
}
115+
}
116+
}
117+
} else {
118+
cbHObj = info.hObj
119+
}
120+
121+
if ok {
83122

84123
gocbc.CallbackArea = info.callbackArea
85124
gocbc.ConnectionArea = info.connectionArea
86125

87126
// Get the data
88127
b := C.GoBytes(unsafe.Pointer(mqBuffer), C.int(mqcbc.DataLength))
89-
90128
// And finally call the user function
91-
info.callbackFunction(info.hObj, gomd, gogmo, b, gocbc, mqreturn)
129+
info.callbackFunction(cbHObj, gomd, gogmo, b, gocbc, mqreturn)
92130
}
93131
}
94132

0 commit comments

Comments
 (0)