CrossNodeManager Reference to Ns0 nodes cause stackoverflow

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
mvdbrand
Sr. Member
Sr. Member
Posts: 17
Joined: 22 Dec 2013, 12:15

CrossNodeManager Reference to Ns0 nodes cause stackoverflow

Post by mvdbrand »

I'm currently testing the Ua C++ SDK. For some days I have been facing a problem with certain references that cause a stackoverflow in the Server. I currently narrowed my issues down to the following problem, I need to point out that i'm using the UaGeneric Objects to create nodes (because I will have some dynamic behaviour in my addressspace in the final solution).

To test I created a very simple server with the default node tree + 2 userdefined ones.

I am creating nodes in different Namespaces. For example Nodes with typedef FolderType that link to eachother
Root->Objects->FolderNs2->FolderNs3. ( see picture attached)
UaSDK issue NS0.jpg
This by using the following API: ( I left out the obvious things as creating the browsename nodemanager etc etc).

Creating (for example) Folder nodes (typedef does not matter for my question for the sake of simplicity i choose Folders here):

Code: Select all

UaGenericObject* pFolderObject2 = new UaGenericObject(
			UaNodeId(102,2),					//const UaNodeId&        nodeId,
			browse_name,					       //const UaQualifiedName& browseName,
			display_name,					      //const UaLocalizedText& displayName,
			description,					      //const UaLocalizedText& description,
			UaNodeId(61,0),					 //const UaNodeId&        typeDefinitionId,  HasTypeDefinition FolderType
			0);			

pNodeManagerConfig->addUaNode(pFolderObject2);

// creates references from Object node -> Folder2 Node
pNodeManagerConfig->addUaReference(UaNodeId(85,0), UaNodeId(102,2), UaNodeId(35,0)); 
Above all works fine with the UA Expert the server can be browsed and we see a Folder2 under Objects which can be browsed. I can create a chain with different nodes in different Namespaces the CrossNamespaceReferences are automaticly created and work fine.

Except when i want to create a reference to a node in NS0. For example my Type defined in Ns2 has a property defined in Ns0 (or Namespace Root). This gives a browse issue.

So I can also create a folder object in NS0 which i reference as follows:

Code: Select all

UaGenericObject* pFolderObjectns0 = new UaGenericObject(
			UaNodeId(100000,0),					//const UaNodeId&        nodeId,
			browse_name,					       //const UaQualifiedName& browseName,
			display_name,					      //const UaLocalizedText& displayName,
			description,					      //const UaLocalizedText& description,
			UaNodeId(61,0),					 //const UaNodeId&        typeDefinitionId,  HasTypeDefinition FolderType
			0);	

pNodeManagerConfigRoot->addUaNode(pFolderObjectns0);
pNodeManagerConfigRoot->addUaReference(UaNodeId(102,2), UaNodeId(100000,0), UaNodeId(35,0)); 

Above will result in a stackoverflow because of the following (see trace)
Starting Node = NS2|Numeric|102
11:39:08.073Z|7|062C* Number of path elements = 1
11:39:08.073Z|7|062C* Path element [0]
11:39:08.087Z|7|062C* TargetName = ns=0|Icon
11:39:08.087Z|7|062C* IsInverse = 0
11:39:08.101Z|7|062C* ReferenceTypeId = NS0|Numeric|46
11:39:08.101Z|7|062C* IncludeSubtypes = 0
11:39:08.101Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.115Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
11:39:08.128Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.128Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
11:39:08.142Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.156Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
11:39:08.156Z|7|008C* --> UaSubscription::checkPublishTimer [SubID=2]
11:39:08.170Z|7|008C* <-- UaSubscription::checkPublishTimer time=100
11:39:08.170Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.184Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
11:39:08.198Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.198Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
11:39:08.226Z|6|062C* --> NodeManagerRoot::translateBrowsePathToNodeId
11:39:08.226Z|6|062C* --> NodeManagerUaNode::translateBrowsePathToNodeId NS=2
.....
Until we have a stack overflow reported by the debugger

If I create the pFolderObjectns0 under a NS0 node in the tree for example Objects the browse works fine. Since the nodemanager for Ns0 is different than Ns1 i also tested by creating references to Ns1 and those work fine just like Ns2 -> Ns3.

This could be either related to NodeManager Ns0 or Ns2 but i only see this translateBrowsePathToNodeId issue when referencing to a node in Ns0. The Nodemanager for Ns0 is a different nodemanager since this one is by default created and fetched by getNodeManagerRoot also looking at the header files I see its implemented by deriving from a different base-class than the others.

I would like to now why I am not able to create references to Ns0 do you need to do something special like connectingStarting Nodes (which i tried but didnt help).

Any suggestions are appreciated,

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by Support Team »

What version of the SDK do you use?
We will try to reproduce the issue with the right version.

Best Regards,
Unified Automation Support Team

mvdbrand
Sr. Member
Sr. Member
Posts: 17
Joined: 22 Dec 2013, 12:15

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by mvdbrand »

Hi,

We are currently using version 1.3.3.
On the day I posted my question I saw that there is a new version released.

In the following days we will port our code to the new SDK, however it will take some time since the new SDK is not 100% backwards compatible with our existing code base.

In addition to my post I would like to add the following:
remark 1:
I know its not allowed to create nodes in NS0 that are not defined by the OPCFoundation. However some nodes are missing on the Server (if you start it up blank). It seems that the Type tree for example is not complete. In NS0 i am creating nodes that are defined by the OPCFoundation and are missing from the AddressSpace.

remark 2:
The issue i described is by using custom folders (to simplify the issue), in reality you would ever create folders in NS0.
The issue is that same with Hierarchical reference to known nodes in NS (thats how I found got into trouble).

mvdbrand
Sr. Member
Sr. Member
Posts: 17
Joined: 22 Dec 2013, 12:15

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by mvdbrand »

Hi,

Im reading through the Changelog for SDK version 1.4 and i found this bugfix very interesting:

Line 814 CHANGELOG.txt

NodeManagerRoot
* Fixed re-adding node manager with same name space
* Replaced browse code in NodeManagerRoot to browse NS0 with call to default
implementation in NodeManagerUaNode
The implementation in NodeManagerRoot did not contain all the error handling implemented
in NodeManagerUaNode::browse. NodeManagerRoot requires special handling to multiplex browse
to the different NodeManagers. But browsing of nodes in namespace 0 can be handled by the
base class NodeManagerUaNode the NodeManagerRoot is derived from.

I did notice in version 1.3.3 that the implementation in NodeManagerUaNode::browse works fine. and NodeManagerRoot didnt use that.

So it could very well be that my issue is actually resolved in version 1.4 (but I need to check it)

mvdbrand
Sr. Member
Sr. Member
Posts: 17
Joined: 22 Dec 2013, 12:15

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by mvdbrand »

Hi,

I have tested my initial posted issue with the new SDK (version 1.4) and I encounter the same stackoverflow as soon as I make a node reference back to a node in NS0 with a hierarchical reference. Traceoutput is similair to the initial report ( seems that the browsepath resolve doenst work correctly for the Root Node Manager ).

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by Support Team »

Hello,

We are able to reproduce the issue and can provide you a simple work around until the issue is solved in the next service release. It is even recommended to use the change long term since it is much more efficient (see explanation later).

First the change, just use another overload of addUaReference() that takes the node pointers instead of the NodeIds.

Code: Select all

UaGenericObject* pFolderObjectns0 = new UaGenericObject(
            UaNodeId(100000,0),               //const UaNodeId&        nodeId,
            browse_name,                      //const UaQualifiedName& browseName,
            display_name,                     //const UaLocalizedText& displayName,
            description,                     //const UaLocalizedText& description,
            UaNodeId(61,0),                //const UaNodeId&        typeDefinitionId,  HasTypeDefinition FolderType
            0);

pNodeManagerConfigRoot->addUaNode(pFolderObjectns0);
// Replace the following line
//pNodeManagerConfigRoot->addUaReference(UaNodeId(102,2), UaNodeId(100000,0), UaNodeId(35,0));
pNodeManagerConfigRoot->addUaReference(pFolderObject2, pFolderObjectns0, UaNodeId(35,0));
If you do not have both node pointer available, you can use the following code:

Code: Select all

pNodeManagerConfigRoot->addUaNode(pFolderObjectns0);
// Replace the following line
//pNodeManagerConfigRoot->addUaReference(UaNodeId(102,2), UaNodeId(100000,0), UaNodeId(35,0));

// Use this code if you do not have the starting node pointer available
NodeManagerRoot* pNMRoot = NodeManagerRoot::CreateRootNodeManager();
UaNode* pNode = pNMRoot->getNode(UaNodeId(102,2));
if ( pNode )
{
    pNodeManagerConfigRoot->addUaReference(pNode->getUaReferenceLists(), pFolderObjectns0, UaNodeId(35,0));
    // getNode() increments the reference counter of the node
    pNode->releaseReference();
}
Background information:
The SDK provides two levels where users can plug in their information, the tool-kit layer and the SDK interfaces. You are using the tool-kit layer at the moment. Most power users with lager applications are implementing SDK interfaces like NodeManager or IOManager directly, especially if they can not hold the whole address space in memory. Tool-kit layer and implementing SDK interfaces directly can be mixed. See documentation for more details:
http://documentation.unified-automation ... Start.html

In the tool-kit layer, the address space resists in memory with nodes and references implementing the Interfaces UaReference and UaNode with derived interfaces like UaObject and UaVariable. Nodes are managed by the tool-kit NodeManager implementation NodeManagerUaNode and references are managed by the nodes through the interface UaReferenceLists.

addUaReference() has two variations, one takes two UaReferenceLists interface pointers (source and target node) and the reference type nodeId and one takes the nodeIds of source and target node and the reference type nodeId. All default node implementations like UaGenericObject implement UaReferenceLists.

By passing in the source and target nodes as pointer, addUaReference() can create the reference directly between the two nodes. This works even if the two nodes are managed by different NodeManagers.

If you pass in the NodeIds of source and target node, addUaReference() tries to find the two nodes in the NodeManager to create the reference between the nodes. If one of the two nodeIds are not managed by the NodeManager, a special connection is created between the two involved NodeManagers. This causes your problem if the target node is managed by the NodeManagerRoot (namespace 0). The special handling is necessary since the NodeManager that implements addUaReference() does not know how the other NodeManager is implemented. It may have no nodes in memory or is implementing the nodes in memory in a complete different way.

Since you know that both nodes are in memory nodes implementing UaReferenceLists, you can use the addUaReference() that takes the two pointers.

Some additional notes:

For better readability of the code you should use the available defines for OPC UA defined nodes:

Code: Select all

pNodeManagerConfig->addUaReference(UaNodeId(85,0), UaNodeId(102,2), UaNodeId(35,0));
->
pNodeManagerConfig->addUaReference(UaNodeId(OpcUaId_ObjectsFolder,0), UaNodeId(102,2), UaNodeId(OpcUaId_Organizes,0));
For namespace 0 you can omit the namespace index and the constructor with numeric identifier und namespace index default value 0 for UaNodeId is automatically used:

Code: Select all

pNodeManagerConfig->addUaReference(UaNodeId(OpcUaId_ObjectsFolder,0), UaNodeId(102,2), UaNodeId(OpcUaId_Organizes,0));
->
pNodeManagerConfig->addUaReference(OpcUaId_ObjectsFolder, UaNodeId(102,2), OpcUaId_Organizes);
For namespaces other than 0 and 1 you should never hard code the namespace index. The NodeManagerConfig interface provides getNameSpaceIndex() to make sure the right namespace index is used even if the order of NodeManager loading is changed in the future.

Code: Select all

pNodeManagerConfig->addUaReference(OpcUaId_ObjectsFolder, UaNodeId(102,2), OpcUaId_Organizes);
->
pNodeManagerConfig->addUaReference(OpcUaId_ObjectsFolder, UaNodeId(102,pNodeManagerConfig->getNameSpaceIndex()), OpcUaId_Organizes);
Best Regards,
Unified Automation Support Team

mvdbrand
Sr. Member
Sr. Member
Posts: 17
Joined: 22 Dec 2013, 12:15

Re: CrossNodeManager Reference to Ns0 nodes cause stackoverf

Post by mvdbrand »

I implemented the proposed workaround and this solves the issue indeed. Great!

about your comments I am well aware of the fact that hardcoding of namespaces and node id's is not something desired, it was only meant as pseudo code (to clearify my question).

Thanks for the quick and thorough reply!

Post Reply