[libvirt] Cannot write data: Broken pipe when accesing libvirt from a forked process

Hi all, I am trying to add vagrant-libvirt support for landrush plugin[0] and found out that libvirt fails for me with: Call to virConnectNumOfNetworks failed: Cannot write data: Broken pipe (Libvirt::RetrieveError) I created a minimal reproducer that causes this: ``` #!/usr/bin/ruby require 'libvirt' conn = Libvirt::open("qemu:///system") fork do puts conn.list_networks end puts conn.list_networks ``` This works just fine on my host, but fails on my virtualized guest (when using nested KVM). The journal shows the following lines in logs: Failed to acquire pid file '/run/user/1001/libvirt/libvirtd.pid': Resource temporarily unavailable So the forked process here tries to access not-existing libvirtd pid file for root (1001 on the VM). Is this a feature/bug? How can one avoid it? Thanks everyone Josef [0] https://github.com/phinze/landrush/pull/124

On Wed, Sep 30, 2015 at 01:06:48PM +0200, Josef Stribny wrote:
Hi all,
I am trying to add vagrant-libvirt support for landrush plugin[0] and found out that libvirt fails for me with:
Call to virConnectNumOfNetworks failed: Cannot write data: Broken pipe (Libvirt::RetrieveError)
I created a minimal reproducer that causes this:
``` #!/usr/bin/ruby require 'libvirt'
conn = Libvirt::open("qemu:///system")
fork do puts conn.list_networks end
puts conn.list_networks ```
This works just fine on my host, but fails on my virtualized guest (when using nested KVM). The journal shows the following lines in logs:
Failed to acquire pid file '/run/user/1001/libvirt/libvirtd.pid': Resource temporarily unavailable
So the forked process here tries to access not-existing libvirtd pid file for root (1001 on the VM).
Is this a feature/bug? How can one avoid it?
It is a bug in your code. You open a connection to libvirt, then fork and then use that single socket connection from two processes. The data sent over the socket will be arbitrary interleaved from the two processes causing corruption of the protocol, so libvirtd kills your connection. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 09/30/2015 10:24 AM, Daniel P. Berrange wrote:
On Wed, Sep 30, 2015 at 01:06:48PM +0200, Josef Stribny wrote:
Hi all,
I am trying to add vagrant-libvirt support for landrush plugin[0] and found out that libvirt fails for me with:
Call to virConnectNumOfNetworks failed: Cannot write data: Broken pipe (Libvirt::RetrieveError)
I created a minimal reproducer that causes this:
``` #!/usr/bin/ruby require 'libvirt'
conn = Libvirt::open("qemu:///system")
fork do puts conn.list_networks end
puts conn.list_networks ```
This works just fine on my host, but fails on my virtualized guest (when using nested KVM). The journal shows the following lines in logs:
Failed to acquire pid file '/run/user/1001/libvirt/libvirtd.pid': Resource temporarily unavailable
So the forked process here tries to access not-existing libvirtd pid file for root (1001 on the VM).
Is this a feature/bug? How can one avoid it?
It is a bug in your code. You open a connection to libvirt, then fork and then use that single socket connection from two processes. The data sent over the socket will be arbitrary interleaved from the two processes causing corruption of the protocol, so libvirtd kills your connection.
Connections can be shared across threads though, so either 1) share the connection object across threads instead of separate processes, 2) open a new connection handle for each separate process - Cole
participants (3)
-
Cole Robinson
-
Daniel P. Berrange
-
Josef Stribny