From dc35274f2f8bdb0f14c83579e1b85c14eda8d3a6 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Fri, 12 Sep 2025 01:27:19 +0300 Subject: [PATCH 1/2] coredump: fix fiber commands of gdb extension Prior to this patch Tarantool GDB-extension failed during loading if `main_cord` symbol is optimized out. As a result fiber-related commands were not available, namely `info tt-fibers` and `tt-fiber`. Closes #1206 @TarantoolBot document Title: Adjusted Tarantool GDB-extension to avoid load failure. --- CHANGELOG.md | 3 +++ cli/coredump/extensions/tarantool-gdb.py | 8 +++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9761830ee..7eccf6daa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed +- `tt coredump`: adjust Tarantool GDB-extention to avoid load failure if `main_cord` + symbol is `optimized out` in gdb session. + ## [2.11.0] - 2025-09-10 The release supports Tarantool Config Storage in `tt cluster failover` commands and diff --git a/cli/coredump/extensions/tarantool-gdb.py b/cli/coredump/extensions/tarantool-gdb.py index dc924af63..23d5fca18 100644 --- a/cli/coredump/extensions/tarantool-gdb.py +++ b/cli/coredump/extensions/tarantool-gdb.py @@ -1560,7 +1560,7 @@ def _init(cls): if not hasattr(cls, '_containers_map'): cls._containers_map = cls.__build_containers_map(cls._containers) - __symbol_re = re.compile('(\w+)(?:\s*\+\s*(\d+))?') + __symbol_re = re.compile(r'(\w+)(?:\s*\+\s*(\d+))?') @classmethod def lookup_entry_info(cls, address): @@ -2582,16 +2582,14 @@ def fiber(): class Cord(object): - __main_cord_fibers = gdb.parse_and_eval('main_cord.alive') - __list_entry_info = RlistLut.lookup_entry_info(__main_cord_fibers.address) - def __init__(self): self.__cord_ptr = cord() def fibers(self): fibers = self.__cord_ptr['alive'] fibers = Rlist(fibers.address) - fibers = map(lambda x: self.__class__.__list_entry_info.container_from_field(x), fibers) + list_entry_info = RlistLut.lookup_entry_info_by_container(ContainerFieldInfo("cord::alive")) + fibers = map(lambda x: list_entry_info.container_from_field(x), fibers) return itertools.chain(fibers, [self.__cord_ptr['sched'].address]) def fiber(self, fid): From 2eba9ef410914341838e744e81c97a8272048a61 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Wed, 23 Jul 2025 12:31:15 +0300 Subject: [PATCH 2/2] cartridge: fix discovery to avoid missing aliases Implementation of cartridge bootstrap in `tt` needs to know aliases of all instances to work properly. Aliases of instances are managed with `membership` module which spreads out certain instance alias across the rest of instances using `gossip` protocol. At the very start of an instance only that instance "knows" its alias, others get this knowledge with some delay. That means in turn that the topology obtained from the different instances might differ in terms of aliases. Prior to this patch topology from a single instance was used and if at that moment this instance haven't collected information about all the aliases, bootstrap failed. Now if any alias is missing we are trying to get it from the topologies obtained from the other instances until all aliases are resolved. The patch fixes flaky test so there is not need to introduce new tests. Closes #TNTP-3709 --- cli/replicaset/cartridge.go | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/cli/replicaset/cartridge.go b/cli/replicaset/cartridge.go index 2350991eb..d1694eef6 100644 --- a/cli/replicaset/cartridge.go +++ b/cli/replicaset/cartridge.go @@ -245,6 +245,7 @@ func (c *CartridgeApplication) discovery() (Replicasets, error) { } if topology.IsBootstrapped { if newTopology.IsBootstrapped { + updateInstancesAliases(newTopology.Replicasets, topology.Replicasets) topology = newTopology } } else { @@ -252,7 +253,8 @@ func (c *CartridgeApplication) discovery() (Replicasets, error) { } // Stop if we already found a valid topology. - return topology.IsBootstrapped && !topology.IsCritical, nil + return topology.IsBootstrapped && !topology.IsCritical && + !hasMissingInstancesAliases(topology.Replicasets), nil }, )) if err != nil { @@ -271,6 +273,37 @@ func (c *CartridgeApplication) discovery() (Replicasets, error) { return recalculateMasters(replicasets), err } +// hasMissingInstancesAliases checks if any instance has empty alias. +func hasMissingInstancesAliases(replicasets []Replicaset) bool { + for _, rs := range replicasets { + for _, inst := range rs.Instances { + if len(inst.Alias) == 0 { + return true + } + } + } + return false +} + +// updateInstancesAliases tries to update missing instances aliases with another instances data. +func updateInstancesAliases(replicasets, other []Replicaset) { + instAliases := make(map[string]string, 0) + for _, rs := range other { + for _, inst := range rs.Instances { + instAliases[inst.UUID] = inst.Alias + } + } + for i, rs := range replicasets { + for ii, inst := range rs.Instances { + if len(inst.Alias) == 0 { + if alias, ok := instAliases[inst.UUID]; ok && len(alias) > 0 { + replicasets[i].Instances[ii].Alias = alias + } + } + } + } +} + // Promote promotes an instance in the cartridge application. func (c *CartridgeApplication) Promote(ctx PromoteCtx) error { replicasets, err := c.Discovery(UseCache)