server: follow TCP port fallback on all interfaces#195
Conversation
Maybe this is the real issue? Having the default applied twice? The first time when there is insufficient information to resolve conflicting TCP port numbers. |
$EPICS_PVAS_INTF_ADDR_LIST filled the configured TCP port into every port-less interface entry (split_addr_into with defaultPort=tcp_port). When the first interface's port was already in use, build() picked a fallback TCP port, but the remaining interfaces were now pinned to the original (unbindable) port and could not follow -- the multi-interface conflict left the server unusable. Pass defaultPort=0 here, matching the client EPICS_PVA_INTF_ADDR_LIST path. A port-less interface then stays at port 0, and the existing acceptor loop (if(addr.port()==0) addr.setPort(effective.tcp_port)) stamps every such interface with the port actually bound, fallback included. This removes the double application of the default the reviewer identified, and drops the server.cpp change from the earlier revision of this branch. testconfig: server INTF list now round-trips port-less, symmetric with the client assertion. testwild.testconflictifaces exercises the multi-interface fallback through the environment as a user configures it.
4070775 to
9348ebc
Compare
|
Good catch — that's the real issue. The default port is applied twice: The client path already does the right thing: I've reworked the branch to fix it there instead: the server One visible consequence worth your call: the server INTF list now round-trips port-less ( Verified: |
A server binding several interfaces aborts if the configured TCP port is in use. The first interface falls back to a dynamically assigned port, but the rest retry the original port, which is still busy, and are not allowed to fall back in turn. The
Serverctor then throws, so an IOC loses its PVA server entirely where a single-interface server would have survived.Reproduce with a second
softIocPVXstarted under:The second IOC reports
while
iocInit()otherwise completes, leaving an IOC with no PVA server at all.Interfaces which do not name a port already adopt
effective.tcp_port, which is how a server withEPICS_PVAS_SERVER_PORT=0puts all of its interfaces on one dynamically assigned port. This change extends that to the port found in use: an interface asking for the server TCP port follows the server onto the port actually bound.Note the bug is only reachable through the environment:
split_addr_into()fills in$EPICS_PVAS_SERVER_PORTfor entries which omit a port, so by the time the interface loop runs, "use the server's port" is spelled either as port zero or as the configured port itself. Both now follow the fallback. An interface naming some other explicit port is a deliberate choice and keeps it.Includes a regression test (
testconflictifacesintestwild.cpp) using the existing wildcard-bind occupancy pattern; it fails deterministically before the fix and passes after (20/20 both ways). It is gated to the Linux IP stack alongside the adjacenttestconflictcase, as it needs a second loopback address.