# Bm\_dev\_mgr\_remove\_port can deadlock the BMI port manager when a packet arrives during the removal

**URL:** https://forum.p4.org/t/bm-dev-mgr-remove-port-can-deadlock-the-bmi-port-manager-when-a-packet-arrives-during-the-removal/1479
**Category:** Getting Started with P4
**Created:** [September 24, 2026, 12:58pm UTC](https://forum.p4.org/t/bm-dev-mgr-remove-port-can-deadlock-the-bmi-port-manager-when-a-packet-arrives-during-the-removal/1479 "2026-09-24T12:58:44Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![louis.barbier41](https://avatars.discourse-cdn.com/v4/letter/l/c77e96/32.png) [@louis.barbier41](https://forum.p4.org/u/louis.barbier41)
#### Post date: [September 24, 2026, 12:58pm UTC](https://forum.p4.org/t/bm-dev-mgr-remove-port-can-deadlock-the-bmi-port-manager-when-a-packet-arrives-during-the-removal/1479/1 "2026-09-24T12:58:44Z")

</div>

Hi everyone,

On a switch that receives traffic, a Thrift bm\_dev\_mgr\_remove\_port sometimes never returns. Afterward the switch forwards nothing, and every later add\_port, remove\_port call hangs too. Only a restart recovers it.

Did someone already have a problem with that ? Do you have a safer way to remove an interface ?

```python
def add_port_via_thrift(thrift_ip, thrift_port, iface_name, port_num, timeout=3.0):
    old_timeout = socket.getdefaulttimeout()
    socket.setdefaulttimeout(timeout)
    try:
        transport = TSocket.TSocket(thrift_ip, thrift_port)
        transport = TTransport.TBufferedTransport(transport)
        protocol = TBinaryProtocol.TBinaryProtocol(transport)
        multiplexed_protocol = TMultiplexedProtocol.TMultiplexedProtocol(protocol, "standard")
        client = Standard.Client(multiplexed_protocol)

        logger.info(f"[thrift] Opening connection for {iface_name}:{port_num}")
        transport.open()
        logger.info(f"[thrift] Connected, calling bm_dev_mgr_add_port for {iface_name}")
        try:
            client.bm_dev_mgr_add_port(iface_name, port_num, "")
            logger.info(f"[thrift] bm_dev_mgr_add_port done for {iface_name}")
        finally:
            transport.close()
    except Exception as e:
        logger.warning(f"[thrift] Failed for {iface_name}: {e}")
        raise
    finally:
        socket.setdefaulttimeout(old_timeout)

def remove_port_via_thrift(thrift_ip, thrift_port, port_num, timeout=3.0):
    old_timeout = socket.getdefaulttimeout()
    socket.setdefaulttimeout(timeout)
    try:
        transport = TSocket.TSocket(thrift_ip, thrift_port)
        transport = TTransport.TBufferedTransport(transport)
        protocol = TBinaryProtocol.TBinaryProtocol(transport)

        multiplexed_protocol = TMultiplexedProtocol.TMultiplexedProtocol(protocol, "standard")
        client = Standard.Client(multiplexed_protocol)

        logger.info(f"[thrift] Opening connection to remove port {port_num}")
        transport.open()
        logger.info(f"[thrift] Connected, calling bm_dev_mgr_remove_port for port {port_num}")
        client.bm_dev_mgr_remove_port(port_num)
        logger.info(f"Port {port_num} successfully removed via Thrift.")
    except Exception as e:
        logger.warning(f"[thrift] Failed to remove port {port_num}: {e}")
        raise
    finally:
        transport.close()
        socket.setdefaulttimeout(old_timeout)

```

```python
#
# Autogenerated by Thrift Compiler (0.16.0)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
# options string: py
#

    def bm_dev_mgr_add_port(self, iface_name, port_num, pcap_path):
        """
        Parameters:
         - iface_name
         - port_num
         - pcap_path

        """
        self.send_bm_dev_mgr_add_port(iface_name, port_num, pcap_path)
        self.recv_bm_dev_mgr_add_port()

    def bm_dev_mgr_remove_port(self, port_num):
        """
        Parameters:
         - port_num

        """
        self.send_bm_dev_mgr_remove_port(port_num)
        self.recv_bm_dev_mgr_remove_port()

```
