All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction
@ 2018-06-05 14:00 Igor Mammedov
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified Igor Mammedov
                   ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-05 14:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor


Commit 047f7038f586d2150f16c6d9ba9cfd0479f0f6ac broke iotests that were using
 -nodefault option, which lead to hang in the early main_loop_wait().
1/2 fixes it by not calling main_loop_wait() unless --preconfig option was on CLI.
1/2 also fixes issue where libvirt starting qemu as daemon waits on qemu parent
process to exit which doens't happen at the early main_loop().
2/2 fixes the same deamon issue but with --preconfig option on CLI

With this QEMU passes make check, make check-block and manual testing with
-daemonize

CC: berrange@redhat.com
CC: mreitz@redhat.com
CC: pbonzini@redhat.com
CC: ehabkost@redhat.com
CC: ldoktor@redhat.com

Igor Mammedov (2):
  cli: Don't run early event loop if no  --preconfig was specified
  vl: fix use of --daemonize with --preconfig

 os-posix.c | 6 ++++++
 vl.c       | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified
  2018-06-05 14:00 [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction Igor Mammedov
@ 2018-06-05 14:00 ` Igor Mammedov
  2018-06-05 18:12   ` Eduardo Habkost
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig Igor Mammedov
  2018-06-06  8:55 ` [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction no-reply
  2 siblings, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-05 14:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor

After 047f7038f586d215 it is possible for event loop to run two
times. First time whilst parsing command line options (the idea
is to bring up monitor early so that management applications can
tweak config before machine is initialized). And the second time
is after everything is set up (this is the usual place). In both
cases the event loop is called as main_loop_wait(nonblocking =
false) which causes the event loop to block until at least one
event occurred.

Now, consider that somebody (i.e. libvirt) calls us with
-daemonize. This operation is split in two steps. The main()
calls os_daemonize() which fork()-s and then waits in read()
until child notifies it via write():

/qemu.git $ ./x86_64-softmmu/qemu-system-x86_64 -S -daemonize \
  -no-user-config -nodefaults -nographic

  main():                child:
    os_daemonize():
      read(pipe[0])

                           main_loop():
                             main_loop_wait(false)

                           os_setup_post():
                             write(pipe[1])

                           main_loop():
                             main_loop_wait(false)

Here it can be clearly seen that main() does not exit until an
event occurs, but at the same time nobody will touch the monitor
socket until their exec("qemu-system-*") finishes. So the whole
thing deadlocks.

The solution is to not call main_loop_wait() unless --preconfig was
specified (in which case caller knows they must connect to the
socket before exec() finishes).

Patch also fixes hang when -nodefaults option is used, which were
causing QEMU hang in the early main_loop_wait() indefinitely by
the same means (not calling main_loop_wait() unless --preconfig
is present on CLI)

Based on
  From: Michal Privoznik <mprivozn@redhat.com>
  Subject: [PATCH] cli: Don't run early event loop if no --preconfig was specified
  Message-Id: <ad910973c593c5ac2fed3a10ea958f7e9c12f82c.1527935663.git.mprivozn@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v2:
  - fix iotests that involve migration,
    rewrite v1 so it would take into account -incoming use case
---
 vl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/vl.c b/vl.c
index c4fe255..fa44138 100644
--- a/vl.c
+++ b/vl.c
@@ -1956,7 +1956,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
-    do {
+    while (!main_loop_should_exit()) {
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
 #endif
@@ -1964,7 +1964,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
 #endif
-    } while (!main_loop_should_exit());
+    }
 }
 
 static void version(void)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 14:00 [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction Igor Mammedov
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified Igor Mammedov
@ 2018-06-05 14:00 ` Igor Mammedov
  2018-06-05 15:13   ` Eric Blake
  2018-06-05 18:30   ` [Qemu-devel] [PATCH v3 " Eduardo Habkost
  2018-06-06  8:55 ` [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction no-reply
  2 siblings, 2 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-05 14:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor

When using --daemonize, the initial lead process will fork a child and
then wait to be notified that setup is complete via a pipe, before it
exits.  When using --preconfig there is an extra call to main_loop()
before the notification is done from os_setup_post(). Thus the parent
process won't exit until the mgmt application connects to the monitor
and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
won't connect to the monitor until daemonizing has completed though.

This is a chicken and egg problem, leading to deadlock at startup.

The only viable way to fix this is to call os_setup_post() before
the early main_loop_wait() call when in RUN_STATE_PRECONFIG. This has
the downside that any errors from this point onwards won't be handled
well by the mgmt application, because it will think QEMU has started
successfully, so not be expecting an abrupt exit. The only way to
deal with that is to move as much user input validation as possible
to before the main_loop() call. This is left as an exercise for
future interested developers.

Based on:
  From: Daniel P. Berrangé <berrange@redhat.com>
  Subject: [PATCH v2 2/2] vl: fix use of --daemonize with --preconfig
  Message-Id: <20180604120345.12955-3-berrange@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v3:
  - rewrite to apply on top of 1/2
---
 os-posix.c | 6 ++++++
 vl.c       | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/os-posix.c b/os-posix.c
index 9ce6f74..ee06a8d 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -309,8 +309,14 @@ void os_daemonize(void)
 
 void os_setup_post(void)
 {
+    static bool os_setup_post_done = false;
     int fd = 0;
 
+    if (os_setup_post_done) {
+        return;
+    }
+    os_setup_post_done = true;
+
     if (daemonize) {
         if (chdir("/")) {
             error_report("not able to chdir to /: %s", strerror(errno));
diff --git a/vl.c b/vl.c
index fa44138..d6fa67f 100644
--- a/vl.c
+++ b/vl.c
@@ -1960,6 +1960,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
 #endif
+        os_setup_post();
         main_loop_wait(false);
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
@@ -4707,7 +4708,6 @@ int main(int argc, char **argv, char **envp)
     }
 
     accel_setup_post(current_machine);
-    os_setup_post();
 
     main_loop();
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig Igor Mammedov
@ 2018-06-05 15:13   ` Eric Blake
  2018-06-05 15:28     ` [Qemu-devel] [PATCH v4 " Igor Mammedov
  2018-06-05 18:30   ` [Qemu-devel] [PATCH v3 " Eduardo Habkost
  1 sibling, 1 reply; 29+ messages in thread
From: Eric Blake @ 2018-06-05 15:13 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: ldoktor, pbonzini, ehabkost, mreitz

On 06/05/2018 09:00 AM, Igor Mammedov wrote:
> When using --daemonize, the initial lead process will fork a child and
> then wait to be notified that setup is complete via a pipe, before it
> exits.  When using --preconfig there is an extra call to main_loop()
> before the notification is done from os_setup_post(). Thus the parent
> process won't exit until the mgmt application connects to the monitor
> and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> won't connect to the monitor until daemonizing has completed though.
> 
> This is a chicken and egg problem, leading to deadlock at startup.
> 
> The only viable way to fix this is to call os_setup_post() before
> the early main_loop_wait() call when in RUN_STATE_PRECONFIG. This has
> the downside that any errors from this point onwards won't be handled
> well by the mgmt application, because it will think QEMU has started
> successfully, so not be expecting an abrupt exit. The only way to
> deal with that is to move as much user input validation as possible
> to before the main_loop() call. This is left as an exercise for
> future interested developers.
> 
> Based on:
>    From: Daniel P. Berrangé <berrange@redhat.com>
>    Subject: [PATCH v2 2/2] vl: fix use of --daemonize with --preconfig
>    Message-Id: <20180604120345.12955-3-berrange@redhat.com>
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> v3:
>    - rewrite to apply on top of 1/2
> ---
>   os-posix.c | 6 ++++++
>   vl.c       | 2 +-
>   2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/os-posix.c b/os-posix.c
> index 9ce6f74..ee06a8d 100644
> --- a/os-posix.c
> +++ b/os-posix.c
> @@ -309,8 +309,14 @@ void os_daemonize(void)
>   
>   void os_setup_post(void)
>   {
> +    static bool os_setup_post_done = false;

The '= false' is not technically necessary; all static variables default 
to zero-initialization.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v4 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 15:13   ` Eric Blake
@ 2018-06-05 15:28     ` Igor Mammedov
  0 siblings, 0 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-05 15:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor, eblake

When using --daemonize, the initial lead process will fork a child and
then wait to be notified that setup is complete via a pipe, before it
exits.  When using --preconfig there is an extra call to main_loop()
before the notification is done from os_setup_post(). Thus the parent
process won't exit until the mgmt application connects to the monitor
and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
won't connect to the monitor until daemonizing has completed though.

This is a chicken and egg problem, leading to deadlock at startup.

The only viable way to fix this is to call os_setup_post() before
the early main_loop_wait() call when in RUN_STATE_PRECONFIG. This has
the downside that any errors from this point onwards won't be handled
well by the mgmt application, because it will think QEMU has started
successfully, so not be expecting an abrupt exit. The only way to
deal with that is to move as much user input validation as possible
to before the main_loop() call. This is left as an exercise for
future interested developers.

Based on:
  From: Daniel P. Berrangé <berrange@redhat.com>
  Subject: [PATCH v2 2/2] vl: fix use of --daemonize with --preconfig
  Message-Id: <20180604120345.12955-3-berrange@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v3:
  - rewrite to apply on top of 1/2
v4:
  - do not init static boolean to false as it's aready false
    (Eric Blake <eblake@redhat.com>)

CC: berrange@redhat.com
CC: mreitz@redhat.com
CC: pbonzini@redhat.com
CC: ehabkost@redhat.com
CC: ldoktor@redhat.com
CC: eblake@redhat.com

---
 os-posix.c | 6 ++++++
 vl.c       | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/os-posix.c b/os-posix.c
index 9ce6f74..0246195 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -309,8 +309,14 @@ void os_daemonize(void)
 
 void os_setup_post(void)
 {
+    static bool os_setup_post_done;
     int fd = 0;
 
+    if (os_setup_post_done) {
+        return;
+    }
+    os_setup_post_done = true;
+
     if (daemonize) {
         if (chdir("/")) {
             error_report("not able to chdir to /: %s", strerror(errno));
diff --git a/vl.c b/vl.c
index fa44138..d6fa67f 100644
--- a/vl.c
+++ b/vl.c
@@ -1960,6 +1960,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
 #endif
+        os_setup_post();
         main_loop_wait(false);
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
@@ -4707,7 +4708,6 @@ int main(int argc, char **argv, char **envp)
     }
 
     accel_setup_post(current_machine);
-    os_setup_post();
 
     main_loop();
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified Igor Mammedov
@ 2018-06-05 18:12   ` Eduardo Habkost
  2018-06-06  7:22     ` Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-05 18:12 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, berrange, mreitz, pbonzini, ldoktor

On Tue, Jun 05, 2018 at 04:00:42PM +0200, Igor Mammedov wrote:
[...]
> Based on
>   From: Michal Privoznik <mprivozn@redhat.com>
>   Subject: [PATCH] cli: Don't run early event loop if no --preconfig was specified
>   Message-Id: <ad910973c593c5ac2fed3a10ea958f7e9c12f82c.1527935663.git.mprivozn@redhat.com>

Michal's patch is already queued on machine-next.  It should be
dropped if this patch gets included, correct?

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig Igor Mammedov
  2018-06-05 15:13   ` Eric Blake
@ 2018-06-05 18:30   ` Eduardo Habkost
  2018-06-06  8:34     ` Igor Mammedov
  2018-06-06  8:37     ` [Qemu-devel] [PATCH v5 " Igor Mammedov
  1 sibling, 2 replies; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-05 18:30 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, berrange, mreitz, pbonzini, ldoktor

On Tue, Jun 05, 2018 at 04:00:43PM +0200, Igor Mammedov wrote:
> When using --daemonize, the initial lead process will fork a child and
> then wait to be notified that setup is complete via a pipe, before it
> exits.  When using --preconfig there is an extra call to main_loop()
> before the notification is done from os_setup_post(). Thus the parent
> process won't exit until the mgmt application connects to the monitor
> and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> won't connect to the monitor until daemonizing has completed though.
> 
> This is a chicken and egg problem, leading to deadlock at startup.
> 
> The only viable way to fix this is to call os_setup_post() before
> the early main_loop_wait() call when in RUN_STATE_PRECONFIG. This has
> the downside that any errors from this point onwards won't be handled
> well by the mgmt application, because it will think QEMU has started
> successfully, so not be expecting an abrupt exit. The only way to
> deal with that is to move as much user input validation as possible
> to before the main_loop() call. This is left as an exercise for
> future interested developers.
> 
> Based on:
>   From: Daniel P. Berrangé <berrange@redhat.com>
>   Subject: [PATCH v2 2/2] vl: fix use of --daemonize with --preconfig
>   Message-Id: <20180604120345.12955-3-berrange@redhat.com>
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> v3:
>   - rewrite to apply on top of 1/2
> ---
>  os-posix.c | 6 ++++++
>  vl.c       | 2 +-
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/os-posix.c b/os-posix.c
> index 9ce6f74..ee06a8d 100644
> --- a/os-posix.c
> +++ b/os-posix.c
> @@ -309,8 +309,14 @@ void os_daemonize(void)
>  
>  void os_setup_post(void)
>  {
> +    static bool os_setup_post_done = false;
>      int fd = 0;
>  
> +    if (os_setup_post_done) {
> +        return;
> +    }
> +    os_setup_post_done = true;
> +

This part is nice because it allows the os_setup_post() call in
the second main loop to be unconditional, but:

>      if (daemonize) {
>          if (chdir("/")) {
>              error_report("not able to chdir to /: %s", strerror(errno));
> diff --git a/vl.c b/vl.c
> index fa44138..d6fa67f 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1960,6 +1960,7 @@ static void main_loop(void)
>  #ifdef CONFIG_PROFILER
>          ti = profile_getclock();
>  #endif
> +        os_setup_post();
>          main_loop_wait(false);

Ensuring the correctness of this os_setup_post() call depends on
reading the whole body of main_loop_should_exit(), which is a
complex and large function.  I think this is too fragile for my
taste.

I prefer Daniel's approach where we have two
os_setup_post()/main_loop() call sites, and the first one is
conditional on --preconfig.


>  #ifdef CONFIG_PROFILER
>          dev_time += profile_getclock() - ti;
> @@ -4707,7 +4708,6 @@ int main(int argc, char **argv, char **envp)
>      }
>  
>      accel_setup_post(current_machine);
> -    os_setup_post();
>  
>      main_loop();
>  
> -- 
> 2.7.4
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified
  2018-06-05 18:12   ` Eduardo Habkost
@ 2018-06-06  7:22     ` Igor Mammedov
  2018-06-11 17:34       ` Eduardo Habkost
  0 siblings, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-06  7:22 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, berrange, mreitz, pbonzini, ldoktor

On Tue, 5 Jun 2018 15:12:46 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Tue, Jun 05, 2018 at 04:00:42PM +0200, Igor Mammedov wrote:
> [...]
> > Based on
> >   From: Michal Privoznik <mprivozn@redhat.com>
> >   Subject: [PATCH] cli: Don't run early event loop if no --preconfig was specified
> >   Message-Id: <ad910973c593c5ac2fed3a10ea958f7e9c12f82c.1527935663.git.mprivozn@redhat.com>  
> 
> Michal's patch is already queued on machine-next.  It should be
> dropped if this patch gets included, correct?
> 
yep, it should be dropped as it has migrations issues.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 18:30   ` [Qemu-devel] [PATCH v3 " Eduardo Habkost
@ 2018-06-06  8:34     ` Igor Mammedov
  2018-06-06  8:37     ` [Qemu-devel] [PATCH v5 " Igor Mammedov
  1 sibling, 0 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-06  8:34 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: qemu-devel, berrange, mreitz, pbonzini, ldoktor

On Tue, 5 Jun 2018 15:30:01 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Tue, Jun 05, 2018 at 04:00:43PM +0200, Igor Mammedov wrote:
> > When using --daemonize, the initial lead process will fork a child and
> > then wait to be notified that setup is complete via a pipe, before it
> > exits.  When using --preconfig there is an extra call to main_loop()
> > before the notification is done from os_setup_post(). Thus the parent
> > process won't exit until the mgmt application connects to the monitor
> > and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> > won't connect to the monitor until daemonizing has completed though.
> > 
> > This is a chicken and egg problem, leading to deadlock at startup.
> > 
> > The only viable way to fix this is to call os_setup_post() before
> > the early main_loop_wait() call when in RUN_STATE_PRECONFIG. This has
> > the downside that any errors from this point onwards won't be handled
> > well by the mgmt application, because it will think QEMU has started
> > successfully, so not be expecting an abrupt exit. The only way to
> > deal with that is to move as much user input validation as possible
> > to before the main_loop() call. This is left as an exercise for
> > future interested developers.
> > 
> > Based on:
> >   From: Daniel P. Berrangé <berrange@redhat.com>
> >   Subject: [PATCH v2 2/2] vl: fix use of --daemonize with --preconfig
> >   Message-Id: <20180604120345.12955-3-berrange@redhat.com>
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > v3:
> >   - rewrite to apply on top of 1/2
> > ---
> >  os-posix.c | 6 ++++++
> >  vl.c       | 2 +-
> >  2 files changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/os-posix.c b/os-posix.c
> > index 9ce6f74..ee06a8d 100644
> > --- a/os-posix.c
> > +++ b/os-posix.c
> > @@ -309,8 +309,14 @@ void os_daemonize(void)
> >  
> >  void os_setup_post(void)
> >  {
> > +    static bool os_setup_post_done = false;
> >      int fd = 0;
> >  
> > +    if (os_setup_post_done) {
> > +        return;
> > +    }
> > +    os_setup_post_done = true;
> > +  
> 
> This part is nice because it allows the os_setup_post() call in
> the second main loop to be unconditional, but:
> 
> >      if (daemonize) {
> >          if (chdir("/")) {
> >              error_report("not able to chdir to /: %s", strerror(errno));
> > diff --git a/vl.c b/vl.c
> > index fa44138..d6fa67f 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -1960,6 +1960,7 @@ static void main_loop(void)
> >  #ifdef CONFIG_PROFILER
> >          ti = profile_getclock();
> >  #endif
> > +        os_setup_post();
> >          main_loop_wait(false);  
> 
> Ensuring the correctness of this os_setup_post() call depends on
> reading the whole body of main_loop_should_exit(), which is a
> complex and large function.  I think this is too fragile for my
> taste.
Fragility was the reason why I moved it into main_loop(),
as os_setup_post() was already overlooked once, since
one would have to make very non-obvious connection with
libvirt requirement to call it before main_loop_wait()
This way call to os_setup_post() will not be forgotten,
and would get an attention whenever main_loop() is concerned.


> I prefer Daniel's approach where we have two
> os_setup_post()/main_loop() call sites, and the first one is
> conditional on --preconfig.
Considering we are unlikely to add one more invocation of main_loop().
I'll post here Daniel's version that applies on top of 1/2 with
a comment so we won't forget about libvirt's requirement
(not the best way to write something robust but better then nothing).
So pick whatever variant would seem the best.


> >  #ifdef CONFIG_PROFILER
> >          dev_time += profile_getclock() - ti;
> > @@ -4707,7 +4708,6 @@ int main(int argc, char **argv, char **envp)
> >      }
> >  
> >      accel_setup_post(current_machine);
> > -    os_setup_post();
> >  
> >      main_loop();
> >  
> > -- 
> > 2.7.4
> >   
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v5 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-05 18:30   ` [Qemu-devel] [PATCH v3 " Eduardo Habkost
  2018-06-06  8:34     ` Igor Mammedov
@ 2018-06-06  8:37     ` Igor Mammedov
  2018-06-06 13:50       ` Eduardo Habkost
  1 sibling, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-06  8:37 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor, eblake

When using --daemonize, the initial lead process will fork a child and
then wait to be notified that setup is complete via a pipe, before it
exits.  When using --preconfig there is an extra call to main_loop()
before the notification is done from os_setup_post(). Thus the parent
process won't exit until the mgmt application connects to the monitor
and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
won't connect to the monitor until daemonizing has completed though.

This is a chicken and egg problem, leading to deadlock at startup.

The only viable way to fix this is to call os_setup_post() before
the early main_loop() call when --preconfig is used. This has the
downside that any errors from this point onwards won't be handled
well by the mgmt application, because it will think QEMU has started
successfully, so not be expecting an abrupt exit. Moving as much user
input validation as possible to before the main_loop() call might help,
but mgmt application should stop assuming that QEMU has started
successfuly and use other means to collect errors from QEMU (logfile).

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v5:
  * use original Daniel's patch [1], but addapt it to apply on top of
    "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
    with extra comment and massage commit message a little bit.

CC: berrange@redhat.com
CC: mreitz@redhat.com
CC: pbonzini@redhat.com
CC: ehabkost@redhat.com
CC: ldoktor@redhat.com
CC: eblake@redhat.com

---
 vl.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/vl.c b/vl.c
index fa44138..ee359e6 100644
--- a/vl.c
+++ b/vl.c
@@ -3038,6 +3038,7 @@ int main(int argc, char **argv, char **envp)
     Error *err = NULL;
     bool list_data_dirs = false;
     char *dir, **dirs;
+    bool os_setup_post_done = false;
     typedef struct BlockdevOptions_queue {
         BlockdevOptions *bdo;
         Location loc;
@@ -4578,6 +4579,13 @@ int main(int argc, char **argv, char **envp)
     parse_numa_opts(current_machine);
 
     /* do monitor/qmp handling at preconfig state if requested */
+    if (!preconfig_exit_requested && is_daemonized()) {
+        /* signal parent QEMU to exit, libvirt treats it as a sign
+         * that monitor socket is ready to accept connections
+         */
+        os_setup_post();
+        os_setup_post_done = true;
+    }
     main_loop();
 
     /* from here on runstate is RUN_STATE_PRELAUNCH */
@@ -4707,8 +4715,10 @@ int main(int argc, char **argv, char **envp)
     }
 
     accel_setup_post(current_machine);
-    os_setup_post();
 
+    if (!os_setup_post_done) {
+        os_setup_post();
+    }
     main_loop();
 
     gdbserver_cleanup();
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction
  2018-06-05 14:00 [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction Igor Mammedov
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified Igor Mammedov
  2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig Igor Mammedov
@ 2018-06-06  8:55 ` no-reply
  2 siblings, 0 replies; 29+ messages in thread
From: no-reply @ 2018-06-06  8:55 UTC (permalink / raw)
  To: imammedo; +Cc: famz, qemu-devel, ldoktor, pbonzini, ehabkost, mreitz

Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1528207243-268226-1-git-send-email-imammedo@redhat.com
Subject: [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
01373291b2 vl: fix use of --daemonize with --preconfig
b6f325357d cli: Don't run early event loop if no --preconfig was specified

=== OUTPUT BEGIN ===
Checking PATCH 1/2: cli: Don't run early event loop if no --preconfig was specified...
Checking PATCH 2/2: vl: fix use of --daemonize with --preconfig...
ERROR: do not initialise statics to 0 or NULL
#44: FILE: os-posix.c:312:
+    static bool os_setup_post_done = false;

total: 1 errors, 0 warnings, 28 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-06  8:37     ` [Qemu-devel] [PATCH v5 " Igor Mammedov
@ 2018-06-06 13:50       ` Eduardo Habkost
  2018-06-07 12:00         ` [Qemu-devel] [PATCH v6 " Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-06 13:50 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, berrange, mreitz, pbonzini, ldoktor, eblake

On Wed, Jun 06, 2018 at 10:37:05AM +0200, Igor Mammedov wrote:
[...]
> @@ -4578,6 +4579,13 @@ int main(int argc, char **argv, char **envp)
>      parse_numa_opts(current_machine);
>  
>      /* do monitor/qmp handling at preconfig state if requested */
> +    if (!preconfig_exit_requested && is_daemonized()) {
> +        /* signal parent QEMU to exit, libvirt treats it as a sign
> +         * that monitor socket is ready to accept connections
> +         */
> +        os_setup_post();
> +        os_setup_post_done = true;
> +    }

I liked your version of os_setup_post() in v3, where the
os_setup_post_done check is done inside os_setup_post().

>      main_loop();
>  
>      /* from here on runstate is RUN_STATE_PRELAUNCH */
> @@ -4707,8 +4715,10 @@ int main(int argc, char **argv, char **envp)
>      }
>  
>      accel_setup_post(current_machine);
> -    os_setup_post();
>  
> +    if (!os_setup_post_done) {
> +        os_setup_post();
> +    }
>      main_loop();
>  
>      gdbserver_cleanup();
> -- 
> 2.7.4
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-06 13:50       ` Eduardo Habkost
@ 2018-06-07 12:00         ` Igor Mammedov
  2018-06-08 13:21           ` Eduardo Habkost
  0 siblings, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-07 12:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: berrange, mreitz, pbonzini, ehabkost, ldoktor, eblake

When using --daemonize, the initial lead process will fork a child and
then wait to be notified that setup is complete via a pipe, before it
exits.  When using --preconfig there is an extra call to main_loop()
before the notification is done from os_setup_post(). Thus the parent
process won't exit until the mgmt application connects to the monitor
and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
won't connect to the monitor until daemonizing has completed though.

This is a chicken and egg problem, leading to deadlock at startup.

The only viable way to fix this is to call os_setup_post() before
the early main_loop() call when --preconfig is used. This has the
downside that any errors from this point onwards won't be handled
well by the mgmt application, because it will think QEMU has started
successfully, so not be expecting an abrupt exit. Moving as much user
input validation as possible to before the main_loop() call might help,
but mgmt application should stop assuming that QEMU has started
successfuly and use other means to collect errors from QEMU (logfile).

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v5:
  * use original Daniel's patch [1], but addapt it to apply on top of
    "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
    with extra comment and massage commit message a little bit.
v6:
  * hide os_setup_post_done flag inside of os_setup_post() as it was in v4

CC: berrange@redhat.com
CC: mreitz@redhat.com
CC: pbonzini@redhat.com
CC: ehabkost@redhat.com
CC: ldoktor@redhat.com
CC: eblake@redhat.com
---
 os-posix.c | 6 ++++++
 vl.c       | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/os-posix.c b/os-posix.c
index 9ce6f74..0246195 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -309,8 +309,14 @@ void os_daemonize(void)
 
 void os_setup_post(void)
 {
+    static bool os_setup_post_done;
     int fd = 0;
 
+    if (os_setup_post_done) {
+        return;
+    }
+    os_setup_post_done = true;
+
     if (daemonize) {
         if (chdir("/")) {
             error_report("not able to chdir to /: %s", strerror(errno));
diff --git a/vl.c b/vl.c
index fa44138..457ff2a 100644
--- a/vl.c
+++ b/vl.c
@@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
     parse_numa_opts(current_machine);
 
     /* do monitor/qmp handling at preconfig state if requested */
+    if (!preconfig_exit_requested && is_daemonized()) {
+        /* signal parent QEMU to exit, libvirt treats it as a sign
+         * that monitor socket is ready to accept connections
+         */
+        os_setup_post();
+    }
     main_loop();
 
     /* from here on runstate is RUN_STATE_PRELAUNCH */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-07 12:00         ` [Qemu-devel] [PATCH v6 " Igor Mammedov
@ 2018-06-08 13:21           ` Eduardo Habkost
  2018-06-11 13:16             ` Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-08 13:21 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: qemu-devel, ldoktor, mreitz, pbonzini, Eric Blake,
	Daniel P. Berrange, Markus Armbruster

On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
> When using --daemonize, the initial lead process will fork a child and
> then wait to be notified that setup is complete via a pipe, before it
> exits.  When using --preconfig there is an extra call to main_loop()
> before the notification is done from os_setup_post(). Thus the parent
> process won't exit until the mgmt application connects to the monitor
> and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> won't connect to the monitor until daemonizing has completed though.
> 
> This is a chicken and egg problem, leading to deadlock at startup.
> 
> The only viable way to fix this is to call os_setup_post() before
> the early main_loop() call when --preconfig is used. This has the
> downside that any errors from this point onwards won't be handled
> well by the mgmt application, because it will think QEMU has started
> successfully, so not be expecting an abrupt exit. Moving as much user
> input validation as possible to before the main_loop() call might help,
> but mgmt application should stop assuming that QEMU has started
> successfuly and use other means to collect errors from QEMU (logfile).
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> v5:
>   * use original Daniel's patch [1], but addapt it to apply on top of
>     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
>     with extra comment and massage commit message a little bit.
> v6:
>   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> 
> CC: berrange@redhat.com
> CC: mreitz@redhat.com
> CC: pbonzini@redhat.com
> CC: ehabkost@redhat.com
> CC: ldoktor@redhat.com
> CC: eblake@redhat.com
> ---
>  os-posix.c | 6 ++++++
>  vl.c       | 6 ++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/os-posix.c b/os-posix.c
> index 9ce6f74..0246195 100644
> --- a/os-posix.c
> +++ b/os-posix.c
> @@ -309,8 +309,14 @@ void os_daemonize(void)
>  
>  void os_setup_post(void)
>  {
> +    static bool os_setup_post_done;
>      int fd = 0;
>  
> +    if (os_setup_post_done) {
> +        return;
> +    }
> +    os_setup_post_done = true;
> +
>      if (daemonize) {
>          if (chdir("/")) {
>              error_report("not able to chdir to /: %s", strerror(errno));
> diff --git a/vl.c b/vl.c
> index fa44138..457ff2a 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
>      parse_numa_opts(current_machine);
>  
>      /* do monitor/qmp handling at preconfig state if requested */
> +    if (!preconfig_exit_requested && is_daemonized()) {
> +        /* signal parent QEMU to exit, libvirt treats it as a sign
> +         * that monitor socket is ready to accept connections
> +         */
> +        os_setup_post();
> +    }

I was looking at the daemonize logic, and noticed it we have a
huge amount of code between this line and the next
os_setup_post() call that could either:

* call exit() and/or error_report(); or
* be unable to finish machine initialization because of
  chdir("/"), change_root(), or change_process_uid().

Doesn't this make -preconfig and -daemonize fundamentally
incompatible?


>      main_loop();
>  
>      /* from here on runstate is RUN_STATE_PRELAUNCH */
> -- 
> 2.7.4
> 
> 

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-08 13:21           ` Eduardo Habkost
@ 2018-06-11 13:16             ` Igor Mammedov
  2018-06-11 19:06               ` Eduardo Habkost
  0 siblings, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-11 13:16 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, ldoktor, mreitz, pbonzini, Eric Blake,
	Daniel P. Berrange, Markus Armbruster

On Fri, 8 Jun 2018 10:21:05 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
> > When using --daemonize, the initial lead process will fork a child and
> > then wait to be notified that setup is complete via a pipe, before it
> > exits.  When using --preconfig there is an extra call to main_loop()
> > before the notification is done from os_setup_post(). Thus the parent
> > process won't exit until the mgmt application connects to the monitor
> > and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> > won't connect to the monitor until daemonizing has completed though.
> > 
> > This is a chicken and egg problem, leading to deadlock at startup.
> > 
> > The only viable way to fix this is to call os_setup_post() before
> > the early main_loop() call when --preconfig is used. This has the
> > downside that any errors from this point onwards won't be handled
> > well by the mgmt application, because it will think QEMU has started
> > successfully, so not be expecting an abrupt exit. Moving as much user
> > input validation as possible to before the main_loop() call might help,
> > but mgmt application should stop assuming that QEMU has started
> > successfuly and use other means to collect errors from QEMU (logfile).
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > v5:
> >   * use original Daniel's patch [1], but addapt it to apply on top of
> >     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
> >     with extra comment and massage commit message a little bit.
> > v6:
> >   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> > 
> > CC: berrange@redhat.com
> > CC: mreitz@redhat.com
> > CC: pbonzini@redhat.com
> > CC: ehabkost@redhat.com
> > CC: ldoktor@redhat.com
> > CC: eblake@redhat.com
> > ---
> >  os-posix.c | 6 ++++++
> >  vl.c       | 6 ++++++
> >  2 files changed, 12 insertions(+)
> > 
> > diff --git a/os-posix.c b/os-posix.c
> > index 9ce6f74..0246195 100644
> > --- a/os-posix.c
> > +++ b/os-posix.c
> > @@ -309,8 +309,14 @@ void os_daemonize(void)
> >  
> >  void os_setup_post(void)
> >  {
> > +    static bool os_setup_post_done;
> >      int fd = 0;
> >  
> > +    if (os_setup_post_done) {
> > +        return;
> > +    }
> > +    os_setup_post_done = true;
> > +
> >      if (daemonize) {
> >          if (chdir("/")) {
> >              error_report("not able to chdir to /: %s", strerror(errno));
> > diff --git a/vl.c b/vl.c
> > index fa44138..457ff2a 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
> >      parse_numa_opts(current_machine);
> >  
> >      /* do monitor/qmp handling at preconfig state if requested */
> > +    if (!preconfig_exit_requested && is_daemonized()) {
> > +        /* signal parent QEMU to exit, libvirt treats it as a sign
> > +         * that monitor socket is ready to accept connections
> > +         */
> > +        os_setup_post();
> > +    }  
> 
> I was looking at the daemonize logic, and noticed it we have a
> huge amount of code between this line and the next
> os_setup_post() call that could either:
> 
> * call exit() and/or error_report(); or
logging would work to the extent mentioned in commit message,
i.e. it' would work fine when log file is used otherwise it
errors will go to /dev/null

so it should be more or less fine on this point

> * be unable to finish machine initialization because of
>   chdir("/"), change_root(), or change_process_uid().
this one really no go.
I see 2 options here,

 * move init code that opens files to early stage (before preconfig monitor)
   or split it to open files early.
   (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
   but there might be code somewhere in callbacks that would do it too,
   so it rather risky to go this route.
   (I'd do this anyways one place at the time using sanitizing
    initialization sequence pretext.)

 * split out signaling part that tells parent process to exit into
   separate helper that's called once before/from main_loop().
   This option seems low risk and additionally error output to
   stderr will work as it does currently (until os_setup_post())

> Doesn't this make -preconfig and -daemonize fundamentally
> incompatible?
Don't see anything that prevents both to work together fundamentally.
essentially -preconfig is extra configuration after CLI,
we potentially would be able execute commands that open files there,
so we should leave chroot & co where it is now.

> 
> 
> >      main_loop();
> >  
> >      /* from here on runstate is RUN_STATE_PRELAUNCH */
> > -- 
> > 2.7.4
> > 
> >   
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified
  2018-06-06  7:22     ` Igor Mammedov
@ 2018-06-11 17:34       ` Eduardo Habkost
  0 siblings, 0 replies; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-11 17:34 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: ldoktor, pbonzini, qemu-devel, mreitz

On Wed, Jun 06, 2018 at 09:22:47AM +0200, Igor Mammedov wrote:
> On Tue, 5 Jun 2018 15:12:46 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
> > On Tue, Jun 05, 2018 at 04:00:42PM +0200, Igor Mammedov wrote:
> > [...]
> > > Based on
> > >   From: Michal Privoznik <mprivozn@redhat.com>
> > >   Subject: [PATCH] cli: Don't run early event loop if no --preconfig was specified
> > >   Message-Id: <ad910973c593c5ac2fed3a10ea958f7e9c12f82c.1527935663.git.mprivozn@redhat.com>  
> > 
> > Michal's patch is already queued on machine-next.  It should be
> > dropped if this patch gets included, correct?
> > 
> yep, it should be dropped as it has migrations issues.

OK, previous patch dequeued, and this one queued.  It will be on
a pull request today.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-11 13:16             ` Igor Mammedov
@ 2018-06-11 19:06               ` Eduardo Habkost
  2018-06-11 21:29                 ` Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-11 19:06 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: qemu-devel, ldoktor, mreitz, pbonzini, Eric Blake,
	Daniel P. Berrange, Markus Armbruster

On Mon, Jun 11, 2018 at 03:16:25PM +0200, Igor Mammedov wrote:
> On Fri, 8 Jun 2018 10:21:05 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
> > On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
> > > When using --daemonize, the initial lead process will fork a child and
> > > then wait to be notified that setup is complete via a pipe, before it
> > > exits.  When using --preconfig there is an extra call to main_loop()
> > > before the notification is done from os_setup_post(). Thus the parent
> > > process won't exit until the mgmt application connects to the monitor
> > > and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> > > won't connect to the monitor until daemonizing has completed though.
> > > 
> > > This is a chicken and egg problem, leading to deadlock at startup.
> > > 
> > > The only viable way to fix this is to call os_setup_post() before
> > > the early main_loop() call when --preconfig is used. This has the
> > > downside that any errors from this point onwards won't be handled
> > > well by the mgmt application, because it will think QEMU has started
> > > successfully, so not be expecting an abrupt exit. Moving as much user
> > > input validation as possible to before the main_loop() call might help,
> > > but mgmt application should stop assuming that QEMU has started
> > > successfuly and use other means to collect errors from QEMU (logfile).
> > > 
> > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > ---
> > > v5:
> > >   * use original Daniel's patch [1], but addapt it to apply on top of
> > >     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
> > >     with extra comment and massage commit message a little bit.
> > > v6:
> > >   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> > > 
> > > CC: berrange@redhat.com
> > > CC: mreitz@redhat.com
> > > CC: pbonzini@redhat.com
> > > CC: ehabkost@redhat.com
> > > CC: ldoktor@redhat.com
> > > CC: eblake@redhat.com
> > > ---
> > >  os-posix.c | 6 ++++++
> > >  vl.c       | 6 ++++++
> > >  2 files changed, 12 insertions(+)
> > > 
> > > diff --git a/os-posix.c b/os-posix.c
> > > index 9ce6f74..0246195 100644
> > > --- a/os-posix.c
> > > +++ b/os-posix.c
> > > @@ -309,8 +309,14 @@ void os_daemonize(void)
> > >  
> > >  void os_setup_post(void)
> > >  {
> > > +    static bool os_setup_post_done;
> > >      int fd = 0;
> > >  
> > > +    if (os_setup_post_done) {
> > > +        return;
> > > +    }
> > > +    os_setup_post_done = true;
> > > +
> > >      if (daemonize) {
> > >          if (chdir("/")) {
> > >              error_report("not able to chdir to /: %s", strerror(errno));
> > > diff --git a/vl.c b/vl.c
> > > index fa44138..457ff2a 100644
> > > --- a/vl.c
> > > +++ b/vl.c
> > > @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
> > >      parse_numa_opts(current_machine);
> > >  
> > >      /* do monitor/qmp handling at preconfig state if requested */
> > > +    if (!preconfig_exit_requested && is_daemonized()) {
> > > +        /* signal parent QEMU to exit, libvirt treats it as a sign
> > > +         * that monitor socket is ready to accept connections
> > > +         */
> > > +        os_setup_post();
> > > +    }  
> > 
> > I was looking at the daemonize logic, and noticed it we have a
> > huge amount of code between this line and the next
> > os_setup_post() call that could either:
> > 
> > * call exit() and/or error_report(); or
> logging would work to the extent mentioned in commit message,
> i.e. it' would work fine when log file is used otherwise it
> errors will go to /dev/null
> 
> so it should be more or less fine on this point

My worry is that most users of error_report() involve an exit()
call too.

Once we have an active monitor, we must never call exit()
directly.  Even qmp_quit() doesn't call exit() directly.

> 
> > * be unable to finish machine initialization because of
> >   chdir("/"), change_root(), or change_process_uid().
> this one really no go.
> I see 2 options here,
> 
>  * move init code that opens files to early stage (before preconfig monitor)
>    or split it to open files early.
>    (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
>    but there might be code somewhere in callbacks that would do it too,
>    so it rather risky to go this route.
>    (I'd do this anyways one place at the time using sanitizing
>     initialization sequence pretext.)

We might have QMP commands that take file paths as input, so is
this really an option?


> 
>  * split out signaling part that tells parent process to exit into
>    separate helper that's called once before/from main_loop().
>    This option seems low risk and additionally error output to
>    stderr will work as it does currently (until os_setup_post())

My assumption is that separating the chdir()/stdout/stderr logic
from the fork/daemonize/exit steps wouldn't be possible without
breaking expectations about -daemonize.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-11 19:06               ` Eduardo Habkost
@ 2018-06-11 21:29                 ` Igor Mammedov
  2018-06-11 22:36                   ` Eduardo Habkost
  0 siblings, 1 reply; 29+ messages in thread
From: Igor Mammedov @ 2018-06-11 21:29 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: qemu-devel, ldoktor, mreitz, pbonzini, Eric Blake,
	Daniel P. Berrange, Markus Armbruster

On Mon, 11 Jun 2018 16:06:07 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Mon, Jun 11, 2018 at 03:16:25PM +0200, Igor Mammedov wrote:
> > On Fri, 8 Jun 2018 10:21:05 -0300
> > Eduardo Habkost <ehabkost@redhat.com> wrote:
> > 
> > > On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
> > > > When using --daemonize, the initial lead process will fork a child and
> > > > then wait to be notified that setup is complete via a pipe, before it
> > > > exits.  When using --preconfig there is an extra call to main_loop()
> > > > before the notification is done from os_setup_post(). Thus the parent
> > > > process won't exit until the mgmt application connects to the monitor
> > > > and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> > > > won't connect to the monitor until daemonizing has completed though.
> > > > 
> > > > This is a chicken and egg problem, leading to deadlock at startup.
> > > > 
> > > > The only viable way to fix this is to call os_setup_post() before
> > > > the early main_loop() call when --preconfig is used. This has the
> > > > downside that any errors from this point onwards won't be handled
> > > > well by the mgmt application, because it will think QEMU has started
> > > > successfully, so not be expecting an abrupt exit. Moving as much user
> > > > input validation as possible to before the main_loop() call might help,
> > > > but mgmt application should stop assuming that QEMU has started
> > > > successfuly and use other means to collect errors from QEMU (logfile).
> > > > 
> > > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > ---
> > > > v5:
> > > >   * use original Daniel's patch [1], but addapt it to apply on top of
> > > >     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
> > > >     with extra comment and massage commit message a little bit.
> > > > v6:
> > > >   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> > > > 
> > > > CC: berrange@redhat.com
> > > > CC: mreitz@redhat.com
> > > > CC: pbonzini@redhat.com
> > > > CC: ehabkost@redhat.com
> > > > CC: ldoktor@redhat.com
> > > > CC: eblake@redhat.com
> > > > ---
> > > >  os-posix.c | 6 ++++++
> > > >  vl.c       | 6 ++++++
> > > >  2 files changed, 12 insertions(+)
> > > > 
> > > > diff --git a/os-posix.c b/os-posix.c
> > > > index 9ce6f74..0246195 100644
> > > > --- a/os-posix.c
> > > > +++ b/os-posix.c
> > > > @@ -309,8 +309,14 @@ void os_daemonize(void)
> > > >  
> > > >  void os_setup_post(void)
> > > >  {
> > > > +    static bool os_setup_post_done;
> > > >      int fd = 0;
> > > >  
> > > > +    if (os_setup_post_done) {
> > > > +        return;
> > > > +    }
> > > > +    os_setup_post_done = true;
> > > > +
> > > >      if (daemonize) {
> > > >          if (chdir("/")) {
> > > >              error_report("not able to chdir to /: %s", strerror(errno));
> > > > diff --git a/vl.c b/vl.c
> > > > index fa44138..457ff2a 100644
> > > > --- a/vl.c
> > > > +++ b/vl.c
> > > > @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
> > > >      parse_numa_opts(current_machine);
> > > >  
> > > >      /* do monitor/qmp handling at preconfig state if requested */
> > > > +    if (!preconfig_exit_requested && is_daemonized()) {
> > > > +        /* signal parent QEMU to exit, libvirt treats it as a sign
> > > > +         * that monitor socket is ready to accept connections
> > > > +         */
> > > > +        os_setup_post();
> > > > +    }  
> > > 
> > > I was looking at the daemonize logic, and noticed it we have a
> > > huge amount of code between this line and the next
> > > os_setup_post() call that could either:
> > > 
> > > * call exit() and/or error_report(); or
> > logging would work to the extent mentioned in commit message,
> > i.e. it' would work fine when log file is used otherwise it
> > errors will go to /dev/null
> > 
> > so it should be more or less fine on this point
> 
> My worry is that most users of error_report() involve an exit()
> call too.
> 
> Once we have an active monitor, we must never call exit()
> directly.  Even qmp_quit() doesn't call exit() directly.
Is there any reason why exit() can't be called?

> > > * be unable to finish machine initialization because of
> > >   chdir("/"), change_root(), or change_process_uid().
> > this one really no go.
> > I see 2 options here,
> > 
> >  * move init code that opens files to early stage (before preconfig monitor)
> >    or split it to open files early.
> >    (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
> >    but there might be code somewhere in callbacks that would do it too,
> >    so it rather risky to go this route.
> >    (I'd do this anyways one place at the time using sanitizing
> >     initialization sequence pretext.)
> 
> We might have QMP commands that take file paths as input, so is
> this really an option?
I'd think that in future we would want to enable object_add in preconfig
to create backends at runtime, so yes we can't do chroot at this point
 

> >  * split out signaling part that tells parent process to exit into
> >    separate helper that's called once before/from main_loop().
> >    This option seems low risk and additionally error output to
> >    stderr will work as it does currently (until os_setup_post())
> 
> My assumption is that separating the chdir()/stdout/stderr logic
> from the fork/daemonize/exit steps wouldn't be possible without
> breaking expectations about -daemonize.
it's already separated and that's what creates one side of problem.
What I suggest is to leave it as is and move out only
  len = write(daemon_pipe, &status, 1);
part of os_setup_post() to sync with parent process. That shouldn't
affect daemonizing flow on QEMU side and would let libvirt reuse parent's
exit as sync point to detect moment when monitor is available.
(patch is in testing, I'll post it tomorrow if it doesn't break tests)

In worst case if we can't do the later in QEMU, mgmt would have to cope with
monitor in preconfig mode without relying on parent exit(0) sync point.
(a typical daemon would fork/chroot and co in one place and clients would use
other means to detect socket availability other than watching parent process
exiting)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-11 21:29                 ` Igor Mammedov
@ 2018-06-11 22:36                   ` Eduardo Habkost
  2018-06-12  9:17                     ` [Qemu-devel] [libvirt] " Michal Privoznik
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-11 22:36 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: qemu-devel, ldoktor, mreitz, pbonzini, Eric Blake,
	Daniel P. Berrange, Markus Armbruster, libvir-list

CCing libvir-list.

On Mon, Jun 11, 2018 at 11:29:24PM +0200, Igor Mammedov wrote:
> On Mon, 11 Jun 2018 16:06:07 -0300
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
> > On Mon, Jun 11, 2018 at 03:16:25PM +0200, Igor Mammedov wrote:
> > > On Fri, 8 Jun 2018 10:21:05 -0300
> > > Eduardo Habkost <ehabkost@redhat.com> wrote:
> > > 
> > > > On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
> > > > > When using --daemonize, the initial lead process will fork a child and
> > > > > then wait to be notified that setup is complete via a pipe, before it
> > > > > exits.  When using --preconfig there is an extra call to main_loop()
> > > > > before the notification is done from os_setup_post(). Thus the parent
> > > > > process won't exit until the mgmt application connects to the monitor
> > > > > and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> > > > > won't connect to the monitor until daemonizing has completed though.
> > > > > 
> > > > > This is a chicken and egg problem, leading to deadlock at startup.
> > > > > 
> > > > > The only viable way to fix this is to call os_setup_post() before
> > > > > the early main_loop() call when --preconfig is used. This has the
> > > > > downside that any errors from this point onwards won't be handled
> > > > > well by the mgmt application, because it will think QEMU has started
> > > > > successfully, so not be expecting an abrupt exit. Moving as much user
> > > > > input validation as possible to before the main_loop() call might help,
> > > > > but mgmt application should stop assuming that QEMU has started
> > > > > successfuly and use other means to collect errors from QEMU (logfile).
> > > > > 
> > > > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > > ---
> > > > > v5:
> > > > >   * use original Daniel's patch [1], but addapt it to apply on top of
> > > > >     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
> > > > >     with extra comment and massage commit message a little bit.
> > > > > v6:
> > > > >   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> > > > > 
> > > > > CC: berrange@redhat.com
> > > > > CC: mreitz@redhat.com
> > > > > CC: pbonzini@redhat.com
> > > > > CC: ehabkost@redhat.com
> > > > > CC: ldoktor@redhat.com
> > > > > CC: eblake@redhat.com
> > > > > ---
> > > > >  os-posix.c | 6 ++++++
> > > > >  vl.c       | 6 ++++++
> > > > >  2 files changed, 12 insertions(+)
> > > > > 
> > > > > diff --git a/os-posix.c b/os-posix.c
> > > > > index 9ce6f74..0246195 100644
> > > > > --- a/os-posix.c
> > > > > +++ b/os-posix.c
> > > > > @@ -309,8 +309,14 @@ void os_daemonize(void)
> > > > >  
> > > > >  void os_setup_post(void)
> > > > >  {
> > > > > +    static bool os_setup_post_done;
> > > > >      int fd = 0;
> > > > >  
> > > > > +    if (os_setup_post_done) {
> > > > > +        return;
> > > > > +    }
> > > > > +    os_setup_post_done = true;
> > > > > +
> > > > >      if (daemonize) {
> > > > >          if (chdir("/")) {
> > > > >              error_report("not able to chdir to /: %s", strerror(errno));
> > > > > diff --git a/vl.c b/vl.c
> > > > > index fa44138..457ff2a 100644
> > > > > --- a/vl.c
> > > > > +++ b/vl.c
> > > > > @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
> > > > >      parse_numa_opts(current_machine);
> > > > >  
> > > > >      /* do monitor/qmp handling at preconfig state if requested */
> > > > > +    if (!preconfig_exit_requested && is_daemonized()) {
> > > > > +        /* signal parent QEMU to exit, libvirt treats it as a sign
> > > > > +         * that monitor socket is ready to accept connections
> > > > > +         */
> > > > > +        os_setup_post();
> > > > > +    }  
> > > > 
> > > > I was looking at the daemonize logic, and noticed it we have a
> > > > huge amount of code between this line and the next
> > > > os_setup_post() call that could either:
> > > > 
> > > > * call exit() and/or error_report(); or
> > > logging would work to the extent mentioned in commit message,
> > > i.e. it' would work fine when log file is used otherwise it
> > > errors will go to /dev/null
> > > 
> > > so it should be more or less fine on this point
> > 
> > My worry is that most users of error_report() involve an exit()
> > call too.
> > 
> > Once we have an active monitor, we must never call exit()
> > directly.  Even qmp_quit() doesn't call exit() directly.
> Is there any reason why exit() can't be called?

QMP clients don't expect the QMP socket to be closed except when
using the 'quit' command.

> 
> > > > * be unable to finish machine initialization because of
> > > >   chdir("/"), change_root(), or change_process_uid().
> > > this one really no go.
> > > I see 2 options here,
> > > 
> > >  * move init code that opens files to early stage (before preconfig monitor)
> > >    or split it to open files early.
> > >    (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
> > >    but there might be code somewhere in callbacks that would do it too,
> > >    so it rather risky to go this route.
> > >    (I'd do this anyways one place at the time using sanitizing
> > >     initialization sequence pretext.)
> > 
> > We might have QMP commands that take file paths as input, so is
> > this really an option?
> I'd think that in future we would want to enable object_add in preconfig
> to create backends at runtime, so yes we can't do chroot at this point
>  
> 
> > >  * split out signaling part that tells parent process to exit into
> > >    separate helper that's called once before/from main_loop().
> > >    This option seems low risk and additionally error output to
> > >    stderr will work as it does currently (until os_setup_post())
> > 
> > My assumption is that separating the chdir()/stdout/stderr logic
> > from the fork/daemonize/exit steps wouldn't be possible without
> > breaking expectations about -daemonize.
> it's already separated and that's what creates one side of problem.

Is it?  Right now '$QEMU -daemonize' will never call exit(0)
before the child process it spawned did the
chdir()/stdout/stderr/etc trick.


> What I suggest is to leave it as is and move out only
>   len = write(daemon_pipe, &status, 1);
> part of os_setup_post() to sync with parent process. That shouldn't
> affect daemonizing flow on QEMU side and would let libvirt reuse parent's
> exit as sync point to detect moment when monitor is available.
> (patch is in testing, I'll post it tomorrow if it doesn't break tests)

This will affect the daemonizing flow, won't it?  It will make
QEMU exit(0) before the child does the chdir()/stderr/stdout/etc
cleanup.  A well-behaved daemon shouldn't do this.

This is probably not a problem for libvirt (which only uses
-daemonize as a sync point for QMP), but possibly a problem for
other users of -daemonize.

> 
> In worst case if we can't do the later in QEMU, mgmt would have to cope with
> monitor in preconfig mode without relying on parent exit(0) sync point.
> (a typical daemon would fork/chroot and co in one place and clients would use
> other means to detect socket availability other than watching parent process
> exiting)

Do we really need to make -daemonize and -preconfig work
together?  libvirt uses -daemonize only for its initial
capability probing, which shouldn't require -preconfig at all.

Even on that case, I wonder why libvirt doesn't simply create a
server socket and waits for QEMU to connect instead of using
-daemonize as a sync point.

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-11 22:36                   ` Eduardo Habkost
@ 2018-06-12  9:17                     ` Michal Privoznik
  2018-06-12 12:42                       ` Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Privoznik @ 2018-06-12  9:17 UTC (permalink / raw)
  To: Eduardo Habkost, Igor Mammedov
  Cc: ldoktor, libvir-list, qemu-devel, mreitz, pbonzini

On 06/12/2018 12:36 AM, Eduardo Habkost wrote:
> CCing libvir-list.
> 
> On Mon, Jun 11, 2018 at 11:29:24PM +0200, Igor Mammedov wrote:
>> On Mon, 11 Jun 2018 16:06:07 -0300
>> Eduardo Habkost <ehabkost@redhat.com> wrote:
>>
>>> On Mon, Jun 11, 2018 at 03:16:25PM +0200, Igor Mammedov wrote:
>>>> On Fri, 8 Jun 2018 10:21:05 -0300
>>>> Eduardo Habkost <ehabkost@redhat.com> wrote:
>>>>
>>>>> On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:
>>>>>> When using --daemonize, the initial lead process will fork a child and
>>>>>> then wait to be notified that setup is complete via a pipe, before it
>>>>>> exits.  When using --preconfig there is an extra call to main_loop()
>>>>>> before the notification is done from os_setup_post(). Thus the parent
>>>>>> process won't exit until the mgmt application connects to the monitor
>>>>>> and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
>>>>>> won't connect to the monitor until daemonizing has completed though.
>>>>>>
>>>>>> This is a chicken and egg problem, leading to deadlock at startup.
>>>>>>
>>>>>> The only viable way to fix this is to call os_setup_post() before
>>>>>> the early main_loop() call when --preconfig is used. This has the
>>>>>> downside that any errors from this point onwards won't be handled
>>>>>> well by the mgmt application, because it will think QEMU has started
>>>>>> successfully, so not be expecting an abrupt exit. Moving as much user
>>>>>> input validation as possible to before the main_loop() call might help,
>>>>>> but mgmt application should stop assuming that QEMU has started
>>>>>> successfuly and use other means to collect errors from QEMU (logfile).
>>>>>>
>>>>>> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>>>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>>>>> ---
>>>>>> v5:
>>>>>>   * use original Daniel's patch [1], but addapt it to apply on top of
>>>>>>     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
>>>>>>     with extra comment and massage commit message a little bit.
>>>>>> v6:
>>>>>>   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
>>>>>>
>>>>>> CC: berrange@redhat.com
>>>>>> CC: mreitz@redhat.com
>>>>>> CC: pbonzini@redhat.com
>>>>>> CC: ehabkost@redhat.com
>>>>>> CC: ldoktor@redhat.com
>>>>>> CC: eblake@redhat.com
>>>>>> ---
>>>>>>  os-posix.c | 6 ++++++
>>>>>>  vl.c       | 6 ++++++
>>>>>>  2 files changed, 12 insertions(+)
>>>>>>
>>>>>> diff --git a/os-posix.c b/os-posix.c
>>>>>> index 9ce6f74..0246195 100644
>>>>>> --- a/os-posix.c
>>>>>> +++ b/os-posix.c
>>>>>> @@ -309,8 +309,14 @@ void os_daemonize(void)
>>>>>>  
>>>>>>  void os_setup_post(void)
>>>>>>  {
>>>>>> +    static bool os_setup_post_done;
>>>>>>      int fd = 0;
>>>>>>  
>>>>>> +    if (os_setup_post_done) {
>>>>>> +        return;
>>>>>> +    }
>>>>>> +    os_setup_post_done = true;
>>>>>> +
>>>>>>      if (daemonize) {
>>>>>>          if (chdir("/")) {
>>>>>>              error_report("not able to chdir to /: %s", strerror(errno));
>>>>>> diff --git a/vl.c b/vl.c
>>>>>> index fa44138..457ff2a 100644
>>>>>> --- a/vl.c
>>>>>> +++ b/vl.c
>>>>>> @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
>>>>>>      parse_numa_opts(current_machine);
>>>>>>  
>>>>>>      /* do monitor/qmp handling at preconfig state if requested */
>>>>>> +    if (!preconfig_exit_requested && is_daemonized()) {
>>>>>> +        /* signal parent QEMU to exit, libvirt treats it as a sign
>>>>>> +         * that monitor socket is ready to accept connections
>>>>>> +         */
>>>>>> +        os_setup_post();
>>>>>> +    }  
>>>>>
>>>>> I was looking at the daemonize logic, and noticed it we have a
>>>>> huge amount of code between this line and the next
>>>>> os_setup_post() call that could either:
>>>>>
>>>>> * call exit() and/or error_report(); or
>>>> logging would work to the extent mentioned in commit message,
>>>> i.e. it' would work fine when log file is used otherwise it
>>>> errors will go to /dev/null
>>>>
>>>> so it should be more or less fine on this point
>>>
>>> My worry is that most users of error_report() involve an exit()
>>> call too.
>>>
>>> Once we have an active monitor, we must never call exit()
>>> directly.  Even qmp_quit() doesn't call exit() directly.
>> Is there any reason why exit() can't be called?
> 
> QMP clients don't expect the QMP socket to be closed except when
> using the 'quit' command.

Libvirt views HANGUP on monitor socket as qemu process dying
unexpectedly so it starts cleanup (which involves 'kill -9' of qemu).

> 
>>
>>>>> * be unable to finish machine initialization because of
>>>>>   chdir("/"), change_root(), or change_process_uid().
>>>> this one really no go.
>>>> I see 2 options here,
>>>>
>>>>  * move init code that opens files to early stage (before preconfig monitor)
>>>>    or split it to open files early.
>>>>    (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
>>>>    but there might be code somewhere in callbacks that would do it too,
>>>>    so it rather risky to go this route.
>>>>    (I'd do this anyways one place at the time using sanitizing
>>>>     initialization sequence pretext.)
>>>
>>> We might have QMP commands that take file paths as input, so is
>>> this really an option?
>> I'd think that in future we would want to enable object_add in preconfig
>> to create backends at runtime, so yes we can't do chroot at this point
>>  
>>
>>>>  * split out signaling part that tells parent process to exit into
>>>>    separate helper that's called once before/from main_loop().
>>>>    This option seems low risk and additionally error output to
>>>>    stderr will work as it does currently (until os_setup_post())
>>>
>>> My assumption is that separating the chdir()/stdout/stderr logic
>>> from the fork/daemonize/exit steps wouldn't be possible without
>>> breaking expectations about -daemonize.
>> it's already separated and that's what creates one side of problem.
> 
> Is it?  Right now '$QEMU -daemonize' will never call exit(0)
> before the child process it spawned did the
> chdir()/stdout/stderr/etc trick.
> 
> 
>> What I suggest is to leave it as is and move out only
>>   len = write(daemon_pipe, &status, 1);
>> part of os_setup_post() to sync with parent process. That shouldn't
>> affect daemonizing flow on QEMU side and would let libvirt reuse parent's
>> exit as sync point to detect moment when monitor is available.
>> (patch is in testing, I'll post it tomorrow if it doesn't break tests)
> 
> This will affect the daemonizing flow, won't it?  It will make
> QEMU exit(0) before the child does the chdir()/stderr/stdout/etc
> cleanup.  A well-behaved daemon shouldn't do this.
> 
> This is probably not a problem for libvirt (which only uses
> -daemonize as a sync point for QMP), but possibly a problem for
> other users of -daemonize.

I think the proper behaviour is to exit(0) after chdir()/stderr/... AND
monitor is set up. Then, if any caller started qemu with -preconfig they
know they can start talking on monitor, set up whatever it is they want
and issue 'cont' finally (or what is the right command to exit preconfig
state). This way nothing changes for callers not using -preconfig.

> 
>>
>> In worst case if we can't do the later in QEMU, mgmt would have to cope with
>> monitor in preconfig mode without relying on parent exit(0) sync point.
>> (a typical daemon would fork/chroot and co in one place and clients would use
>> other means to detect socket availability other than watching parent process
>> exiting)
> 
> Do we really need to make -daemonize and -preconfig work
> together?  libvirt uses -daemonize only for its initial
> capability probing, which shouldn't require -preconfig at all.
> 
> Even on that case, I wonder why libvirt doesn't simply create a
> server socket and waits for QEMU to connect instead of using
> -daemonize as a sync point.
> 

because libvirt views qemu as well behaved daemon. Should anything go
wrong libvirt reads qemu's stderr and reports error to upper layers.

Michal

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12  9:17                     ` [Qemu-devel] [libvirt] " Michal Privoznik
@ 2018-06-12 12:42                       ` Igor Mammedov
  2018-06-12 12:50                         ` Daniel P. Berrangé
  2018-06-12 13:04                         ` Michal Privoznik
  0 siblings, 2 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-12 12:42 UTC (permalink / raw)
  To: Michal Privoznik
  Cc: Eduardo Habkost, ldoktor, libvir-list, qemu-devel, mreitz,
	pbonzini, berrange, pkrempa

On Tue, 12 Jun 2018 11:17:15 +0200
Michal Privoznik <mprivozn@redhat.com> wrote:

> On 06/12/2018 12:36 AM, Eduardo Habkost wrote:
> > CCing libvir-list.
> > 
> > On Mon, Jun 11, 2018 at 11:29:24PM +0200, Igor Mammedov wrote:  
> >> On Mon, 11 Jun 2018 16:06:07 -0300
> >> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >>  
> >>> On Mon, Jun 11, 2018 at 03:16:25PM +0200, Igor Mammedov wrote:  
> >>>> On Fri, 8 Jun 2018 10:21:05 -0300
> >>>> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >>>>  
> >>>>> On Thu, Jun 07, 2018 at 02:00:09PM +0200, Igor Mammedov wrote:  
> >>>>>> When using --daemonize, the initial lead process will fork a child and
> >>>>>> then wait to be notified that setup is complete via a pipe, before it
> >>>>>> exits.  When using --preconfig there is an extra call to main_loop()
> >>>>>> before the notification is done from os_setup_post(). Thus the parent
> >>>>>> process won't exit until the mgmt application connects to the monitor
> >>>>>> and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application
> >>>>>> won't connect to the monitor until daemonizing has completed though.
> >>>>>>
> >>>>>> This is a chicken and egg problem, leading to deadlock at startup.
> >>>>>>
> >>>>>> The only viable way to fix this is to call os_setup_post() before
> >>>>>> the early main_loop() call when --preconfig is used. This has the
> >>>>>> downside that any errors from this point onwards won't be handled
> >>>>>> well by the mgmt application, because it will think QEMU has started
> >>>>>> successfully, so not be expecting an abrupt exit. Moving as much user
> >>>>>> input validation as possible to before the main_loop() call might help,
> >>>>>> but mgmt application should stop assuming that QEMU has started
> >>>>>> successfuly and use other means to collect errors from QEMU (logfile).
> >>>>>>
> >>>>>> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> >>>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >>>>>> ---
> >>>>>> v5:
> >>>>>>   * use original Daniel's patch [1], but addapt it to apply on top of
> >>>>>>     "[PATCH v3 1/2] cli: Don't run early event loop if no  --preconfig was specified"
> >>>>>>     with extra comment and massage commit message a little bit.
> >>>>>> v6:
> >>>>>>   * hide os_setup_post_done flag inside of os_setup_post() as it was in v4
> >>>>>>
> >>>>>> CC: berrange@redhat.com
> >>>>>> CC: mreitz@redhat.com
> >>>>>> CC: pbonzini@redhat.com
> >>>>>> CC: ehabkost@redhat.com
> >>>>>> CC: ldoktor@redhat.com
> >>>>>> CC: eblake@redhat.com
> >>>>>> ---
> >>>>>>  os-posix.c | 6 ++++++
> >>>>>>  vl.c       | 6 ++++++
> >>>>>>  2 files changed, 12 insertions(+)
> >>>>>>
> >>>>>> diff --git a/os-posix.c b/os-posix.c
> >>>>>> index 9ce6f74..0246195 100644
> >>>>>> --- a/os-posix.c
> >>>>>> +++ b/os-posix.c
> >>>>>> @@ -309,8 +309,14 @@ void os_daemonize(void)
> >>>>>>  
> >>>>>>  void os_setup_post(void)
> >>>>>>  {
> >>>>>> +    static bool os_setup_post_done;
> >>>>>>      int fd = 0;
> >>>>>>  
> >>>>>> +    if (os_setup_post_done) {
> >>>>>> +        return;
> >>>>>> +    }
> >>>>>> +    os_setup_post_done = true;
> >>>>>> +
> >>>>>>      if (daemonize) {
> >>>>>>          if (chdir("/")) {
> >>>>>>              error_report("not able to chdir to /: %s", strerror(errno));
> >>>>>> diff --git a/vl.c b/vl.c
> >>>>>> index fa44138..457ff2a 100644
> >>>>>> --- a/vl.c
> >>>>>> +++ b/vl.c
> >>>>>> @@ -4578,6 +4578,12 @@ int main(int argc, char **argv, char **envp)
> >>>>>>      parse_numa_opts(current_machine);
> >>>>>>  
> >>>>>>      /* do monitor/qmp handling at preconfig state if requested */
> >>>>>> +    if (!preconfig_exit_requested && is_daemonized()) {
> >>>>>> +        /* signal parent QEMU to exit, libvirt treats it as a sign
> >>>>>> +         * that monitor socket is ready to accept connections
> >>>>>> +         */
> >>>>>> +        os_setup_post();
> >>>>>> +    }    
> >>>>>
> >>>>> I was looking at the daemonize logic, and noticed it we have a
> >>>>> huge amount of code between this line and the next
> >>>>> os_setup_post() call that could either:
> >>>>>
> >>>>> * call exit() and/or error_report(); or  
> >>>> logging would work to the extent mentioned in commit message,
> >>>> i.e. it' would work fine when log file is used otherwise it
> >>>> errors will go to /dev/null
> >>>>
> >>>> so it should be more or less fine on this point  
> >>>
> >>> My worry is that most users of error_report() involve an exit()
> >>> call too.
> >>>
> >>> Once we have an active monitor, we must never call exit()
> >>> directly.  Even qmp_quit() doesn't call exit() directly.  
> >> Is there any reason why exit() can't be called?  
> > 
> > QMP clients don't expect the QMP socket to be closed except when
> > using the 'quit' command.  
> 
> Libvirt views HANGUP on monitor socket as qemu process dying
> unexpectedly so it starts cleanup (which involves 'kill -9' of qemu).
So if we exit(1) there is a chance to get SIGKILL before exit(1) completes.
Do we care about it at this point?
(there are places when QEMU calls exit(1) at runtime on unrecoverable error)

> >>>>> * be unable to finish machine initialization because of
> >>>>>   chdir("/"), change_root(), or change_process_uid().  
> >>>> this one really no go.
> >>>> I see 2 options here,
> >>>>
> >>>>  * move init code that opens files to early stage (before preconfig monitor)
> >>>>    or split it to open files early.
> >>>>    (I've spotted several obvious places fwcfg/vnc/replay_start/migration)
> >>>>    but there might be code somewhere in callbacks that would do it too,
> >>>>    so it rather risky to go this route.
> >>>>    (I'd do this anyways one place at the time using sanitizing
> >>>>     initialization sequence pretext.)  
> >>>
> >>> We might have QMP commands that take file paths as input, so is
> >>> this really an option?  
> >> I'd think that in future we would want to enable object_add in preconfig
> >> to create backends at runtime, so yes we can't do chroot at this point
> >>  
> >>  
> >>>>  * split out signaling part that tells parent process to exit into
> >>>>    separate helper that's called once before/from main_loop().
> >>>>    This option seems low risk and additionally error output to
> >>>>    stderr will work as it does currently (until os_setup_post())  
> >>>
> >>> My assumption is that separating the chdir()/stdout/stderr logic
> >>> from the fork/daemonize/exit steps wouldn't be possible without
> >>> breaking expectations about -daemonize.  
> >> it's already separated and that's what creates one side of problem.  
> > 
> > Is it?  Right now '$QEMU -daemonize' will never call exit(0)
> > before the child process it spawned did the
> > chdir()/stdout/stderr/etc trick.
> > 
> >   
> >> What I suggest is to leave it as is and move out only
> >>   len = write(daemon_pipe, &status, 1);
> >> part of os_setup_post() to sync with parent process. That shouldn't
> >> affect daemonizing flow on QEMU side and would let libvirt reuse parent's
> >> exit as sync point to detect moment when monitor is available.
> >> (patch is in testing, I'll post it tomorrow if it doesn't break tests)  
> > 
> > This will affect the daemonizing flow, won't it?  It will make
> > QEMU exit(0) before the child does the chdir()/stderr/stdout/etc
> > cleanup.  A well-behaved daemon shouldn't do this.
> > 
> > This is probably not a problem for libvirt (which only uses
> > -daemonize as a sync point for QMP), but possibly a problem for
> > other users of -daemonize.  
> 
> I think the proper behaviour is to exit(0) after chdir()/stderr/... AND
> monitor is set up. Then, if any caller started qemu with -preconfig they
> know they can start talking on monitor, set up whatever it is they want
> and issue 'cont' finally (or what is the right command to exit preconfig
> state). This way nothing changes for callers not using -preconfig.
As pointed out earlier we need -preconfig stay before chdir/chroot/chuid/stderr/stdout
are called, so it would have the same access rights/permissions for configuration
as CLI options.

> >> In worst case if we can't do the later in QEMU, mgmt would have to cope with
> >> monitor in preconfig mode without relying on parent exit(0) sync point.
> >> (a typical daemon would fork/chroot and co in one place and clients would use
> >> other means to detect socket availability other than watching parent process
> >> exiting)  
> > 
> > Do we really need to make -daemonize and -preconfig work
> > together?  libvirt uses -daemonize only for its initial
> > capability probing, which shouldn't require -preconfig at all.
> > 
> > Even on that case, I wonder why libvirt doesn't simply create a
> > server socket and waits for QEMU to connect instead of using
> > -daemonize as a sync point.
> >   
> 
> because libvirt views qemu as well behaved daemon. Should anything go
> wrong libvirt reads qemu's stderr and reports error to upper layers.
We can keep daemonizing flow in QEMU as it's now.
But Eduardo's idea about libvirt created socked + letting QEMU connect to it
has a merit. It should fix current deadlock issue with as monitor
won't be depending on lead exit event.
Can we do this way on libvirt side when --preconfig is in use
(it might even be fine for normal flow without -preconfig)?

> Michal

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12 12:42                       ` Igor Mammedov
@ 2018-06-12 12:50                         ` Daniel P. Berrangé
  2018-06-13 14:17                           ` Eduardo Habkost
  2018-06-12 13:04                         ` Michal Privoznik
  1 sibling, 1 reply; 29+ messages in thread
From: Daniel P. Berrangé @ 2018-06-12 12:50 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Michal Privoznik, Eduardo Habkost, ldoktor, libvir-list,
	qemu-devel, mreitz, pbonzini, pkrempa

On Tue, Jun 12, 2018 at 02:42:05PM +0200, Igor Mammedov wrote:
> We can keep daemonizing flow in QEMU as it's now.
> But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> has a merit. It should fix current deadlock issue with as monitor
> won't be depending on lead exit event.

NB, libvirt only ever uses --daemonize when probing capabilities, never
when launching QEMU for a real VM. In the latter case, we now use FD
passing, so libvirt opens the UNIX domain socket listener, and passes
this into QEMU. So libvirt knows it can connect to the listener
immediately and will only ever get a failure if QEMU has exited.

We can't use FD passing for the capabilities probing because of the
chicken & egg problem - we need to probe capabilities to find out
if FD passing it available or not. Fortunately with capabilities
probing, we don't care about using --preconfig, as were not running
a real VM

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12 12:42                       ` Igor Mammedov
  2018-06-12 12:50                         ` Daniel P. Berrangé
@ 2018-06-12 13:04                         ` Michal Privoznik
  2018-06-12 13:10                           ` Peter Krempa
  2018-06-12 13:17                           ` Daniel P. Berrangé
  1 sibling, 2 replies; 29+ messages in thread
From: Michal Privoznik @ 2018-06-12 13:04 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Eduardo Habkost, ldoktor, libvir-list, qemu-devel, mreitz,
	pbonzini, berrange, pkrempa

On 06/12/2018 02:42 PM, Igor Mammedov wrote:

>>>
>>> Do we really need to make -daemonize and -preconfig work
>>> together?  libvirt uses -daemonize only for its initial
>>> capability probing, which shouldn't require -preconfig at all.
>>>
>>> Even on that case, I wonder why libvirt doesn't simply create a
>>> server socket and waits for QEMU to connect instead of using
>>> -daemonize as a sync point.
>>>   
>>
>> because libvirt views qemu as well behaved daemon. Should anything go
>> wrong libvirt reads qemu's stderr and reports error to upper layers.
> We can keep daemonizing flow in QEMU as it's now.
> But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> has a merit. It should fix current deadlock issue with as monitor
> won't be depending on lead exit event.

Not sure about the benefits. Currently, libvirt spawns qemu, waits for
monitor to show up (currently, the timeout dynamic depending on some
black magic involving guest RAM size) and if it does not show up in time
it kills qemu. The same algorithm must be kept in place even for case
when libvirt would pass pre-opened socket to qemu in case qemu deadlocks
before being able to communicate over qmp. The only advantage I see is
libvirt would not need to label the socket (set uid:gid, selinux, ...).
On the other hand, since it would be libvirt creating the socket what
would happen on libvirtd restart?

> Can we do this way on libvirt side when --preconfig is in use
> (it might even be fine for normal flow without -preconfig)?

I think passing pre-opened socket and --preconfig are orthogonal. What
if somebody wants to use --preconfig does not pass any FD?

Michal

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12 13:04                         ` Michal Privoznik
@ 2018-06-12 13:10                           ` Peter Krempa
  2018-06-12 13:17                           ` Daniel P. Berrangé
  1 sibling, 0 replies; 29+ messages in thread
From: Peter Krempa @ 2018-06-12 13:10 UTC (permalink / raw)
  To: Michal Privoznik
  Cc: Igor Mammedov, ldoktor, Eduardo Habkost, libvir-list, qemu-devel,
	mreitz, pbonzini

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

On Tue, Jun 12, 2018 at 15:04:42 +0200, Michal Privoznik wrote:
> On 06/12/2018 02:42 PM, Igor Mammedov wrote:
> 
> >>>
> >>> Do we really need to make -daemonize and -preconfig work
> >>> together?  libvirt uses -daemonize only for its initial
> >>> capability probing, which shouldn't require -preconfig at all.
> >>>
> >>> Even on that case, I wonder why libvirt doesn't simply create a
> >>> server socket and waits for QEMU to connect instead of using
> >>> -daemonize as a sync point.
> >>>   
> >>
> >> because libvirt views qemu as well behaved daemon. Should anything go
> >> wrong libvirt reads qemu's stderr and reports error to upper layers.
> > We can keep daemonizing flow in QEMU as it's now.
> > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > has a merit. It should fix current deadlock issue with as monitor
> > won't be depending on lead exit event.
> 
> Not sure about the benefits. Currently, libvirt spawns qemu, waits for
> monitor to show up (currently, the timeout dynamic depending on some
> black magic involving guest RAM size) and if it does not show up in time
> it kills qemu. The same algorithm must be kept in place even for case
> when libvirt would pass pre-opened socket to qemu in case qemu deadlocks
> before being able to communicate over qmp. The only advantage I see is
> libvirt would not need to label the socket (set uid:gid, selinux, ...).
> On the other hand, since it would be libvirt creating the socket what
> would happen on libvirtd restart?

Well, if qemu deadlocks just after spewing out the monitor greeting you
end up in the same situation as the timeout code is not applied later
for regular monitor communication.

Depending on how early the preconfig state happens, keeping in the
timeout may be pointless.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12 13:04                         ` Michal Privoznik
  2018-06-12 13:10                           ` Peter Krempa
@ 2018-06-12 13:17                           ` Daniel P. Berrangé
  1 sibling, 0 replies; 29+ messages in thread
From: Daniel P. Berrangé @ 2018-06-12 13:17 UTC (permalink / raw)
  To: Michal Privoznik
  Cc: Igor Mammedov, Eduardo Habkost, ldoktor, libvir-list, qemu-devel,
	mreitz, pbonzini, pkrempa

On Tue, Jun 12, 2018 at 03:04:42PM +0200, Michal Privoznik wrote:
> On 06/12/2018 02:42 PM, Igor Mammedov wrote:
> 
> >>>
> >>> Do we really need to make -daemonize and -preconfig work
> >>> together?  libvirt uses -daemonize only for its initial
> >>> capability probing, which shouldn't require -preconfig at all.
> >>>
> >>> Even on that case, I wonder why libvirt doesn't simply create a
> >>> server socket and waits for QEMU to connect instead of using
> >>> -daemonize as a sync point.
> >>>   
> >>
> >> because libvirt views qemu as well behaved daemon. Should anything go
> >> wrong libvirt reads qemu's stderr and reports error to upper layers.
> > We can keep daemonizing flow in QEMU as it's now.
> > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > has a merit. It should fix current deadlock issue with as monitor
> > won't be depending on lead exit event.
> 
> Not sure about the benefits. Currently, libvirt spawns qemu, waits for
> monitor to show up (currently, the timeout dynamic depending on some
> black magic involving guest RAM size) and if it does not show up in time
> it kills qemu. The same algorithm must be kept in place even for case
> when libvirt would pass pre-opened socket to qemu in case qemu deadlocks
> before being able to communicate over qmp. The only advantage I see is
> libvirt would not need to label the socket (set uid:gid, selinux, ...).

As mentioned in my other reply, we already do FD passing, and that code
has intentionally got rid of the timeout, because timeouts cause false
failures to launch QEMU. This is a particular problem when using many
disks that are encrypted, since LUKS encryption has a minimum 1 second
delay on opening each disk, so with many disks we're at risk of hitting
the timeout even when QEMU is still starting normally.

I don't see a reason to special case startup with timeouts to deal
with hangs, while ignoring the possibility of hangs after initial
startup.

> On the other hand, since it would be libvirt creating the socket what
> would happen on libvirtd restart?

We're creating a *listener* socket, not a client connection, so on
restart we simply connect again as normal.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-12 12:50                         ` Daniel P. Berrangé
@ 2018-06-13 14:17                           ` Eduardo Habkost
  2018-06-13 14:23                             ` Daniel P. Berrangé
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-13 14:17 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Igor Mammedov, Michal Privoznik, ldoktor, libvir-list,
	qemu-devel, mreitz, pbonzini, pkrempa

On Tue, Jun 12, 2018 at 01:50:33PM +0100, Daniel P. Berrangé wrote:
> On Tue, Jun 12, 2018 at 02:42:05PM +0200, Igor Mammedov wrote:
> > We can keep daemonizing flow in QEMU as it's now.
> > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > has a merit. It should fix current deadlock issue with as monitor
> > won't be depending on lead exit event.
> 
> NB, libvirt only ever uses --daemonize when probing capabilities, never
> when launching QEMU for a real VM. In the latter case, we now use FD
> passing, so libvirt opens the UNIX domain socket listener, and passes
> this into QEMU. So libvirt knows it can connect to the listener
> immediately and will only ever get a failure if QEMU has exited.

So, what I'm really missing here is: do we have a good reason to
support --daemonize + --preconfig today?

The options I see are:

1) complete daemonization before preconfig main loop
----------------------------------------------------

By "complete daemonization" I mean doing chdir("/"),
stderr/stdout cleanup, chroot, and UID magic before calling
exit(0) on the main QEMU process.

Pros:
* More intuitive

Cons:
* Can break existing initialization code that don't expect
  this to happen.
  (can this be fixed?)
* Can break any preconfig-time QMP commands that rely on opening
  files
  (is it a real problem?)
* Any initialization error conditions that currently rely on
  error_report()+exit() will be very inconvenient to handle
  properly
  (this can be fixed eventually, but it's not trivial)


2) incomplete daemonization before preconfig main loop
------------------------------------------------------

This means calling exit(0) on the main process before doing the
chdir/stderr/etc magic.

Pros:
* Less likely to break initialization code and other QMP commands

Cons:
* Not what's expected from a well-behaved daemon.
  (If we're not daemonizing properly, what's the point of using
  -daemonize at all?)
* More difficult to change behavior later.


3) daemonize only after leaving preconfig state
-----------------------------------------------

AFAICS, this is the current behavior.

Pros:
* Less likely to break init code
* Keeps existing code as is

Cons:
* Less intuitive
* -daemonize becomes useless as synchronization point for monitor
  availability
* Would this be useful for anybody, at all?
* We won't be able to change this behavior later


4) Not supporting -preconfig + -daemonize
-----------------------------------------

Pros:
* Simple to implement.
* Avoids unexpected bugs.
* Saves our time.
* We can change this behavior later.

Cons:
* People might want us to support it eventually.



I believe the only reasonable options are (1) and (4).

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-13 14:17                           ` Eduardo Habkost
@ 2018-06-13 14:23                             ` Daniel P. Berrangé
  2018-06-13 17:09                               ` Eduardo Habkost
  0 siblings, 1 reply; 29+ messages in thread
From: Daniel P. Berrangé @ 2018-06-13 14:23 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Igor Mammedov, Michal Privoznik, ldoktor, libvir-list,
	qemu-devel, mreitz, pbonzini, pkrempa

On Wed, Jun 13, 2018 at 11:17:30AM -0300, Eduardo Habkost wrote:
> On Tue, Jun 12, 2018 at 01:50:33PM +0100, Daniel P. Berrangé wrote:
> > On Tue, Jun 12, 2018 at 02:42:05PM +0200, Igor Mammedov wrote:
> > > We can keep daemonizing flow in QEMU as it's now.
> > > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > > has a merit. It should fix current deadlock issue with as monitor
> > > won't be depending on lead exit event.
> > 
> > NB, libvirt only ever uses --daemonize when probing capabilities, never
> > when launching QEMU for a real VM. In the latter case, we now use FD
> > passing, so libvirt opens the UNIX domain socket listener, and passes
> > this into QEMU. So libvirt knows it can connect to the listener
> > immediately and will only ever get a failure if QEMU has exited.
> 
> So, what I'm really missing here is: do we have a good reason to
> support --daemonize + --preconfig today?

On the libvirt zero, I don't see a compelling need for it.

> The options I see are:
> 
> 1) complete daemonization before preconfig main loop
> ----------------------------------------------------
> 
> By "complete daemonization" I mean doing chdir("/"),
> stderr/stdout cleanup, chroot, and UID magic before calling
> exit(0) on the main QEMU process.
> 
> Pros:
> * More intuitive
> 
> Cons:
> * Can break existing initialization code that don't expect
>   this to happen.
>   (can this be fixed?)
> * Can break any preconfig-time QMP commands that rely on opening
>   files
>   (is it a real problem?)

NB Use of -chroot is separate from -daemonize, so it is not
an issue with -preconfig + -daemonize alone.

There's soo many caveats around -chroot, I struggle to
care about adding another caveats.

> * Any initialization error conditions that currently rely on
>   error_report()+exit() will be very inconvenient to handle
>   properly
>   (this can be fixed eventually, but it's not trivial)


> 3) daemonize only after leaving preconfig state
> -----------------------------------------------
> 
> AFAICS, this is the current behavior.
> 
> Pros:
> * Less likely to break init code
> * Keeps existing code as is
> 
> Cons:
> * Less intuitive
> * -daemonize becomes useless as synchronization point for monitor
>   availability

Yeah that honestly kills the key benefit of having -daemonize
imho.

> * Would this be useful for anybody, at all?
> * We won't be able to change this behavior later
> 
> 

> I believe the only reasonable options are (1) and (4).

Agreed.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-13 14:23                             ` Daniel P. Berrangé
@ 2018-06-13 17:09                               ` Eduardo Habkost
  2018-06-14 12:32                                 ` Igor Mammedov
  0 siblings, 1 reply; 29+ messages in thread
From: Eduardo Habkost @ 2018-06-13 17:09 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Igor Mammedov, Michal Privoznik, ldoktor, libvir-list,
	qemu-devel, mreitz, pbonzini, pkrempa

On Wed, Jun 13, 2018 at 03:23:09PM +0100, Daniel P. Berrangé wrote:
> On Wed, Jun 13, 2018 at 11:17:30AM -0300, Eduardo Habkost wrote:
> > On Tue, Jun 12, 2018 at 01:50:33PM +0100, Daniel P. Berrangé wrote:
> > > On Tue, Jun 12, 2018 at 02:42:05PM +0200, Igor Mammedov wrote:
> > > > We can keep daemonizing flow in QEMU as it's now.
> > > > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > > > has a merit. It should fix current deadlock issue with as monitor
> > > > won't be depending on lead exit event.
> > > 
> > > NB, libvirt only ever uses --daemonize when probing capabilities, never
> > > when launching QEMU for a real VM. In the latter case, we now use FD
> > > passing, so libvirt opens the UNIX domain socket listener, and passes
> > > this into QEMU. So libvirt knows it can connect to the listener
> > > immediately and will only ever get a failure if QEMU has exited.
> > 
> > So, what I'm really missing here is: do we have a good reason to
> > support --daemonize + --preconfig today?
> 
> On the libvirt zero, I don't see a compelling need for it.

Good. :)

> > The options I see are:
> > 1) complete daemonization before preconfig main loop
[...]
> > 4) Not supporting -preconfig + -daemonize
[...]
> > I believe the only reasonable options are (1) and (4).
> 
> Agreed.

If it was up to me, I would just go with (4) because it's
simpler.

But if somebody wants to implement (1), the caveats should be
clearly documented.  I would prefer to simply document
"--daemonize --preconfig" as experimental, with something like:

  "Note: usage of --daemonize with the --preconfig option is
  experimental, because it can prevent QEMU from reporting
  machine initialization errors and prevent some features from
  working after QEMU is daemonized."

-- 
Eduardo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [libvirt] [PATCH v6 2/2] vl: fix use of --daemonize with --preconfig
  2018-06-13 17:09                               ` Eduardo Habkost
@ 2018-06-14 12:32                                 ` Igor Mammedov
  0 siblings, 0 replies; 29+ messages in thread
From: Igor Mammedov @ 2018-06-14 12:32 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Daniel P. Berrangé,
	Michal Privoznik, ldoktor, libvir-list, qemu-devel, mreitz,
	pbonzini, pkrempa

On Wed, 13 Jun 2018 14:09:32 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Wed, Jun 13, 2018 at 03:23:09PM +0100, Daniel P. Berrangé wrote:
> > On Wed, Jun 13, 2018 at 11:17:30AM -0300, Eduardo Habkost wrote:  
> > > On Tue, Jun 12, 2018 at 01:50:33PM +0100, Daniel P. Berrangé wrote:  
> > > > On Tue, Jun 12, 2018 at 02:42:05PM +0200, Igor Mammedov wrote:  
> > > > > We can keep daemonizing flow in QEMU as it's now.
> > > > > But Eduardo's idea about libvirt created socked + letting QEMU connect to it
> > > > > has a merit. It should fix current deadlock issue with as monitor
> > > > > won't be depending on lead exit event.  
> > > > 
> > > > NB, libvirt only ever uses --daemonize when probing capabilities, never
> > > > when launching QEMU for a real VM. In the latter case, we now use FD
> > > > passing, so libvirt opens the UNIX domain socket listener, and passes
> > > > this into QEMU. So libvirt knows it can connect to the listener
> > > > immediately and will only ever get a failure if QEMU has exited.  
> > > 
> > > So, what I'm really missing here is: do we have a good reason to
> > > support --daemonize + --preconfig today?  
> > 
> > On the libvirt zero, I don't see a compelling need for it.  
> 
> Good. :)
> 
> > > The options I see are:
> > > 1) complete daemonization before preconfig main loop  
> [...]
> > > 4) Not supporting -preconfig + -daemonize  
> [...]
> > > I believe the only reasonable options are (1) and (4).  
> > 
> > Agreed.  
> 
> If it was up to me, I would just go with (4) because it's
> simpler.
Let's just disable it for now. it will be easier to allow it
than take it back later.

> 
> But if somebody wants to implement (1), the caveats should be
> clearly documented.  I would prefer to simply document
> "--daemonize --preconfig" as experimental, with something like:
> 
>   "Note: usage of --daemonize with the --preconfig option is
>   experimental, because it can prevent QEMU from reporting
>   machine initialization errors and prevent some features from
>   working after QEMU is daemonized."

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-06-14 12:32 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-05 14:00 [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction Igor Mammedov
2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified Igor Mammedov
2018-06-05 18:12   ` Eduardo Habkost
2018-06-06  7:22     ` Igor Mammedov
2018-06-11 17:34       ` Eduardo Habkost
2018-06-05 14:00 ` [Qemu-devel] [PATCH v3 2/2] vl: fix use of --daemonize with --preconfig Igor Mammedov
2018-06-05 15:13   ` Eric Blake
2018-06-05 15:28     ` [Qemu-devel] [PATCH v4 " Igor Mammedov
2018-06-05 18:30   ` [Qemu-devel] [PATCH v3 " Eduardo Habkost
2018-06-06  8:34     ` Igor Mammedov
2018-06-06  8:37     ` [Qemu-devel] [PATCH v5 " Igor Mammedov
2018-06-06 13:50       ` Eduardo Habkost
2018-06-07 12:00         ` [Qemu-devel] [PATCH v6 " Igor Mammedov
2018-06-08 13:21           ` Eduardo Habkost
2018-06-11 13:16             ` Igor Mammedov
2018-06-11 19:06               ` Eduardo Habkost
2018-06-11 21:29                 ` Igor Mammedov
2018-06-11 22:36                   ` Eduardo Habkost
2018-06-12  9:17                     ` [Qemu-devel] [libvirt] " Michal Privoznik
2018-06-12 12:42                       ` Igor Mammedov
2018-06-12 12:50                         ` Daniel P. Berrangé
2018-06-13 14:17                           ` Eduardo Habkost
2018-06-13 14:23                             ` Daniel P. Berrangé
2018-06-13 17:09                               ` Eduardo Habkost
2018-06-14 12:32                                 ` Igor Mammedov
2018-06-12 13:04                         ` Michal Privoznik
2018-06-12 13:10                           ` Peter Krempa
2018-06-12 13:17                           ` Daniel P. Berrangé
2018-06-06  8:55 ` [Qemu-devel] [PATCH v3 0/2] fix -nodefaults and -daemonize regressions caused by --preconfig introduction no-reply

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.