When a server decides to close a client, the virNetServerClientCloseLocked() is called. In here various cleanup steps are taken, but the most important part (from this commit's POV at least) is the way that the socket is closed. Firstly, removal of the socket associated with the client from the event loop is signalized and then the socket is unrefed. The socket is not closed just yet though, because the event loop holds a reference to it. This reference will be freed as soon as the event loop wakes up and starts issuing callbacks (in this case virNetSocketEventFree()). So far, this is how things usually work. But if the daemon reaches the number of opened files limit, things start to work differently. If the RLIMIT_NOFILE limit is reached and there's a client that wants to connect then the event loop wakes up, sees POLLIN on the socket and calls virNetServerServiceAccept() which in turn calls virNetSocketAccept(). But because of the limit, accept() fails with EMFILE leaving the POLLIN event unhandled. The dispatch then continues to next FDs with events on them. BUT, it will NOT call the socket removal callback (virNetSocketEventFree()) because it has low priority (G_PRIORITY_DEFAULT_IDLE). Per glib's documentation: * Each event source is assigned a priority. The default priority, * %G_PRIORITY_DEFAULT, is 0. Values less than 0 denote higher priorities. * Values greater than 0 denote lower priorities. Events from high priority * sources are always processed before events from lower priority sources. and per g_idle_add() documentation: * Adds a function to be called whenever there are no higher priority * events pending to the default main loop. The function is given the * default idle priority, %G_PRIORITY_DEFAULT_IDLE. Now, because we did not accept() the client we are constantly seeing POLLIN on the main socket and thus the removal of the client socket won't ever happen. The fix is to set at least the same priority as other sources, but since we want to just close an FD, let's give it the highest priority and call it before handling other events. This issue can be easily reproduced, for instance: # ulimit -S -n 40 (tweak this number if needed) # ./src/libvirtd from another terminal: # for ((i=0; i<100; i++)); do virsh list & done; virsh list The last `virsh list` must not get stuck. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2007168 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Libvirt API for virtualization
Libvirt provides a portable, long term stable C API for managing the virtualization technologies provided by many operating systems. It includes support for QEMU, KVM, Xen, LXC, bhyve, Virtuozzo, VMware vCenter and ESX, VMware Desktop, Hyper-V, VirtualBox and the POWER Hypervisor.
For some of these hypervisors, it provides a stateful management daemon which runs on the virtualization host allowing access to the API both by non-privileged local users and remote users.
Layered packages provide bindings of the libvirt C API into other languages including Python, Perl, PHP, Go, Java, OCaml, as well as mappings into object systems such as GObject, CIM and SNMP.
Further information about the libvirt project can be found on the website:
License
The libvirt C API is distributed under the terms of GNU Lesser
General Public License, version 2.1 (or later). Some parts of the code
that are not part of the C library may have the more restrictive GNU
General Public License, version 2.0 (or later). See the files
COPYING.LESSER
and COPYING
for full license
terms & conditions.
Installation
Instructions on building and installing libvirt can be found on the website:
https://libvirt.org/compiling.html
Contributing
The libvirt project welcomes contributions in many ways. For most components the best way to contribute is to send patches to the primary development mailing list. Further guidance on this can be found on the website:
https://libvirt.org/contribute.html
Contact
The libvirt project has two primary mailing lists:
- libvirt-users@redhat.com (for user discussions)
- libvir-list@redhat.com (for development only)
Further details on contacting the project are available on the website: