This is an alternate method of solving the problem detailed in: https://bugzilla.redhat.com/show_bug.cgi?id=816465 Testing has shown that if we "reserve" the bind address of "pid of libvirtd" so that libnl never tries to bind it, our bind of "pid of libnl + (1 << 22)" (which is what libnl ends up using for the 2nd socket it binds) will *always* succeed the first time. The way to make this reservation is to allocate a handle from libnl (it internally assigns the address it will use at handle alloc time), then just never use that handle - it is a place holder for whatever other code in the process is using netlink sockets directly (i.e. not through libnl). The advantage of this patch over the other is that it doesn't rely on timing at all. The disadvantage (?maybe? maybe not, I'm not sure - someone more knowledgeable about the libvirtd<->lldpad communication please inform) is that the bind address used by the netlink socket that communicates with lldpad will be "pid of libvirtd + (1 << 22)", not "pid of libvirtd". --- src/util/virnetlink.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c index b2e9d51..aca0c07 100644 --- a/src/util/virnetlink.c +++ b/src/util/virnetlink.c @@ -68,6 +68,7 @@ struct _virNetlinkEventSrvPrivate { int eventwatch; int netlinkfd; struct nl_handle *netlinknh; + struct nl_handle *dummy_netlinknh; /*Events*/ int handled; size_t handlesCount; @@ -286,6 +287,7 @@ virNetlinkEventServiceStop(void) virNetlinkEventServerLock(srv); nl_close(srv->netlinknh); nl_handle_destroy(srv->netlinknh); + nl_handle_destroy(srv->dummy_netlinknh); virEventRemoveHandle(srv->eventwatch); /* free any remaining clients on the list */ @@ -345,13 +347,24 @@ virNetlinkEventServiceStart(void) virNetlinkEventServerLock(srv); + srv->netlinknh = NULL; + /* Allocate a dummy nl_handle to reserve the address "pid of + * libvirtd" for whatever library is using it. + */ + srv->dummy_netlinknh = nl_handle_alloc(); + if (!srv->dummy_netlinknh) { + virReportSystemError(errno, "%s", + _("cannot allocate space holder nlhandle for virNetlinkEvent server")); + goto error_server; + } + /* Allocate a new socket and get fd */ srv->netlinknh = nl_handle_alloc(); if (!srv->netlinknh) { virReportSystemError(errno, "%s", _("cannot allocate nlhandle for virNetlinkEvent server")); - goto error_locked; + goto error_server; } if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) { @@ -391,10 +404,14 @@ virNetlinkEventServiceStart(void) error_server: if (ret < 0) { - nl_close(srv->netlinknh); - nl_handle_destroy(srv->netlinknh); + if (srv->netlinknh) { + nl_close(srv->netlinknh); + nl_handle_destroy(srv->netlinknh); + } + if (srv->dummy_netlinknh) { + nl_handle_destroy(srv->dummy_netlinknh); + } } -error_locked: virNetlinkEventServerUnlock(srv); if (ret < 0) { virMutexDestroy(&srv->lock); -- 1.7.10 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list