From e29e02a8c6c0b36a0158321cf01368bfd772a185 Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Mon, 15 Jun 2026 12:49:01 +0800 Subject: [PATCH] Fix: revert IOU lock optimization, serialize IOU node creation for correct application_id assignment The _iou_id_lock must cover _create_node() because get_next_application_id() checks in-memory nodes (self._nodes), which are only registered after _create_node() completes. Without this serialization, concurrent IOU node creation produces duplicate application IDs. --- gns3server/controller/project.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 535e414a8..fdd50c7c5 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -620,18 +620,17 @@ class Project: if node_type == "iou": async with self._iou_id_lock: - # Only hold the lock while allocating a unique application ID to avoid - # serializing the HTTP call to the compute across all IOU nodes. - # Multiple IOU nodes can be created concurrently once IDs are assigned. + # IOU application IDs must be allocated serially to avoid duplicates. + # The lock must also cover _create_node() because get_next_application_id() + # checks in-memory nodes (self._nodes), which are only registered + # after _create_node() completes. if "properties" in kwargs.keys(): - # allocate a new application id for nodes loaded from the project kwargs.get("properties")["application_id"] = get_next_application_id( self._controller.projects, self._computes ) elif "application_id" not in kwargs.keys() and not kwargs.get("properties"): - # allocate a new application id for nodes added to the project kwargs["application_id"] = get_next_application_id(self._controller.projects, self._computes) - node = await self._create_node(compute, name, node_id, node_type, **kwargs) + node = await self._create_node(compute, name, node_id, node_type, **kwargs) else: node = await self._create_node(compute, name, node_id, node_type, **kwargs) self.emit_notification("node.created", node.asdict())