I have a method in my OPCUA server (based on C++SDKv1.8.3) that takes two input arguments and everything works fine when I call the method from an OPCUA client, UaExpert for example, with valid input. However, if the input is invalid, the OPCUA server crashes because of a segmentation fault! Reading documentation and looking in the examples does not clearly explain if I do something wrong... Doc says: "pCallback: Callback interface used for the transaction. The MethodManager must use this interface to finish the action for each passed node in the transaction.". So, I interpret this as I must always call callback->finishCall, ok? However, this leads to a segfault.
Here's the situation explained in more detail:
- My MethodManager subclass overrides the virtual beginCall method.
- In my MethodManager subclass beginCall method I check the inputArguments and if they are not valid I create an inputArgumentResult array of size 2 with elements set to OpcUa_BadInvalidArgument and I also set the overall statusCode to OpcUa_BadInvalidArgument. Furthermore I create a one-element uavariant-int32 outputArgument array with value set to -1.
- In my MethodManager subclass beginCall method I then finish the call transaction by calling finishCall-method on the input pCallback pointer (of type UaCallContext) with the arguments just explained. The last thing that happens in UaCallContext::finishCall is that it deletes itself: delete this; (in uatransactionmanager.cpp).
- After this, my MethodManager subclass beginCall-method immediatly returns to UaTransactionManager::executeMethodCall with the OpcUa_BadInvalidArgument return value.
- UaTransactionManager::executeMethodCall checks if the return value is good, which it isn't, so it then tries to call pUaCallContext->finishCall. Problem is that pUaCallContext object has been deleted (by itself) already, which leads to undefined behaviour and results in a segfault crash.
So, please can you explain how this shall be handled? IMO, the documentation does not clearly say how to handle this. One guess from my side is that my MethodManagerSubClass:beginCall-method should always call callback->finishCall (as doc says?) and unintuitively always return OpcUa_Good (as doc does not say?) from my MethodManagerSubClass:beginCall-method. Another guess is that my MethodManagerSubClass:beginCall-method should only call callback->finishCall if the method call could be handled fully in my server and return OpcUa_Good, otherwise I should return a OpcUa_Bad and, counter to what the documentation says, not call callback->finishCall. I don't know which is best, and maybe there is yet another way that I have overlooked?
Regards,
/Tommy