A listener bound to a specific address stays in NetX's port-only listen table after the interface holding that address is removed: listeners have no connect_interface (nx_tcp_server_socket_listen.c:112), so ami_ns_interface_users() (src/netstack/netstack.c:2232) does not count them and the remove succeeds. A later connection to another local address on the same port is completed by the SYN cache, then refused by bsd_bind_accepts(), and accept() returns EWOULDBLOCK even on a blocking socket (src/bsdsocket/socket.c:2239-2250).
Repro: bind(A:P), listen(), blocking accept(); RemoveNetInterface A's interface (succeeds); connect to B:P over another interface; accept() returns -1, errno 35.
Expected: a blocking accept keeps waiting (the refused peer is reset), never EWOULDBLOCK.
Test: behavioural, host tier on bsd_accept with a mismatched connect_interface on a blocking socket; assert it loops rather than returning.
🤖 Generated with Claude Code
A listener bound to a specific address stays in NetX's port-only listen table after the interface holding that address is removed: listeners have no
connect_interface(nx_tcp_server_socket_listen.c:112), soami_ns_interface_users()(src/netstack/netstack.c:2232) does not count them and the remove succeeds. A later connection to another local address on the same port is completed by the SYN cache, then refused bybsd_bind_accepts(), andaccept()returnsEWOULDBLOCKeven on a blocking socket (src/bsdsocket/socket.c:2239-2250).Repro:
bind(A:P),listen(), blockingaccept();RemoveNetInterfaceA's interface (succeeds); connect to B:P over another interface;accept()returns -1, errno 35.Expected: a blocking accept keeps waiting (the refused peer is reset), never EWOULDBLOCK.
Test: behavioural, host tier on
bsd_acceptwith a mismatchedconnect_interfaceon a blocking socket; assert it loops rather than returning.🤖 Generated with Claude Code