Daniel P. Berrange wrote:
The attached patch fixes two issues

 - It explicitly checks to see if the requested /usr/bin/qemu* binary
   actually exists before fork()/exec()'ing it. While its technically
   possible to catch the execve() failure of ENOENT, its a real pain to
   feed this error back to the qemu daemon because we're in a sub-process
   at that point. The obvious & easy solution is to thus check to see if
   the binary exists before trying to fork.

This is quite a hard problem to fix properly, as I'm sure you know.

If we were to change to use execvp, so making libvirt less dependent on the precise location of qemu binaries[1] then a complete test would also need to parse $PATH.

With SELinux an exec can fail for a lot more reasons than just lack of the binary or lack of execute bit.

And additionally, just because we manage to execvp the qemu-* binary, that doesn't mean that it initialises fully. In Real Life rpm ensures that we can't install libvirt without having qemu, so qemu initialisation failures are likely to be far more common than cannot-exec-qemu failures.

Olwm (the old OpenLook window manager) solved both problems in this way. From the olwm man page[2]:

     -syncpid process-id
          When olwm has completed  its  initialization,  it  will
          send  a  signal (SIGALRM by default) to process-id. The
          signal will be sent only if  this  option  is  present.
          This  is  useful  for  running  olwm from shell scripts
          (such as .xinitrc) in such a way that the script  waits
          for  olwm  to  finish its initialization, while leaving
          olwm as a child process of the shell script.  This  can
          be done using the following sh(1) construct:

               sleep 15 & pid=$!
               olwm -syncpid $pid &
               wait $pid


     -syncsignal signal
          Specifies the signal to send instead of  SIGALRM.   The
          signal is specified as a number, not symbolically.

(In the shell-script example shown there is no way to catch errors, but you can easily extend this by sending SIGALRM to the parent -- indicating correct exec + initialisation -- or timing out).

OK, so this requires an upstream patch to qemu. Worth getting this in now with the view that a few years down the line it'll be useful?

In the present, qemu has two features which seem to allow us to detect partial or full initialisation.

The -daemonize flag in qemu explicitly allows you to do this. They use a pipe from the child back to the parent which sends a signal back to the parent after full initialisation has happened. Unfortunately this means that qemu is not only not a child of libvirt, but also we no longer have access to stdin/stdout (ie. console). We would need to make another (good) change to allow qemu to write console sockets into a well-known directory using qemu -monitor unix:/var/...

The -pidfile flag is a more immediate, partial solution. The pidfile is written part way through initialisation -- the qemu process has been exec'd and has done some work, and then works its way through the command line arguments until it reaches this one, whereupon it creates the file immediately. After parsing command line arguments, some further initialisation is done, so this is not a full solution.

What do people think?  Worth me working on fixing this problem properly?

Rich.

[1] It's arguable whether we should do that, or rely on configure-time detection of the binaries. Perhaps configure-time configuration is more secure.

[2] http://www.umanitoba.ca/cgi-bin/man.cgi?section=1&topic=olwm

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to