All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] util/log: Always send errors to logfile when daemonized
@ 2022-10-19 15:16 Greg Kurz
  2022-10-19 15:16 ` [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall Greg Kurz
  2022-10-19 15:16 ` [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized Greg Kurz
  0 siblings, 2 replies; 14+ messages in thread
From: Greg Kurz @ 2022-10-19 15:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Daniel P . Berrangé,
	Richard Henderson, Paolo Bonzini, Greg Kurz

When QEMU is started with `--daemonize -D ${logfile} -d ${some_log_item}`,
error logs from error_report() and friends go to ${logfile}, but if QEMU
is started with `-daemonize -D ${logfile}` and no `-d`, the file isn't
even created and all logs go to /dev/null.

This inconsistency is quite confusing for users and gives the impression
that QEMU doesn't log errors at all. It seems much saner to always create
the log file when `-D` was passed and to be able to report errors.

It was spotted by the kata-containers project, which happens to do just
that `--daemonize -D` without `-d` trick. It is possible that they will
stop doing so and catch errors through QEMU's stderr at some point, but
I'm posting the patches anyway.

v2:
- new log_thread_id() implementation for hosts without gettid() syscall
- avoid conflict between global log file and per-thread logfile
- style improvements

Greg Kurz (2):
  util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  util/log: Always send errors to logfile when daemonized

 util/log.c | 56 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 14 deletions(-)

-- 
2.37.3




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

* [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  2022-10-19 15:16 [PATCH v2 0/2] util/log: Always send errors to logfile when daemonized Greg Kurz
@ 2022-10-19 15:16 ` Greg Kurz
  2022-10-19 15:57   ` Daniel P. Berrangé
  2022-10-19 15:16 ` [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized Greg Kurz
  1 sibling, 1 reply; 14+ messages in thread
From: Greg Kurz @ 2022-10-19 15:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Daniel P . Berrangé,
	Richard Henderson, Paolo Bonzini, Greg Kurz

A subsequent patch needs to be able to differentiate the main QEMU
thread from other threads. An obvious way to do so is to compare
log_thread_id() and getpid(), based on the fact that they are equal
for the main thread on systems that have the gettid() syscall (e.g.
linux).

Adapt the fallback code for systems without gettid() to provide the
same assumption.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
---
 util/log.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/util/log.c b/util/log.c
index d6eb0378c3a3..e1c2535cfcd2 100644
--- a/util/log.c
+++ b/util/log.c
@@ -72,8 +72,13 @@ static int log_thread_id(void)
 #elif defined(SYS_gettid)
     return syscall(SYS_gettid);
 #else
+    static __thread int my_id = -1;
     static int counter;
-    return qatomic_fetch_inc(&counter);
+
+    if (my_id == -1) {
+        my_id = getpid() + qatomic_fetch_inc(&counter);
+    }
+    return my_id;
 #endif
 }
 
-- 
2.37.3



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

* [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-19 15:16 [PATCH v2 0/2] util/log: Always send errors to logfile when daemonized Greg Kurz
  2022-10-19 15:16 ` [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall Greg Kurz
@ 2022-10-19 15:16 ` Greg Kurz
  2022-10-20  2:21   ` Richard Henderson
  1 sibling, 1 reply; 14+ messages in thread
From: Greg Kurz @ 2022-10-19 15:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Daniel P . Berrangé,
	Richard Henderson, Paolo Bonzini, Greg Kurz

When QEMU is started with `-daemonize`, all stdio descriptors get
redirected to `/dev/null`. This basically means that anything
printed with error_report() and friends is lost.

One could hope that passing `-D ${logfile}` would cause the messages
to go to `${logfile}`, as the documentation tends to suggest:

      -D logfile
              Output log in logfile instead of to stderr

Unfortunately, `-D` belongs to the logging framework and it only
does this redirection if some log item is also enabled with `-d`
or if QEMU was configured with `--enable-trace-backend=log`. A
typical production setup doesn't do tracing or fine-grain
debugging but it certainly needs to collect errors.

Ignore the check on enabled log items when QEMU is daemonized. Previous
behaviour is retained for the non-daemonized case. The logic is unrolled
as an `if` for better readability. Since qemu_set_log_internal() caches
the final log level and the per-thread property in global variables, it
seems more correct to check these instead of intermediary local variables.

Special care is needed for the `-D ${logfile} -d tid` case : `${logfile}`
is expected to be a template that contains exactly one `%d` that should be
expanded to a PID or TID. The logic in qemu_log_trylock() already takes
care of that for per-thread logs. Do it as well for the QEMU main thread
when opening the file.

Note that qemu_log_trylock() now must ensure that the main QEMU thread
only uses the global log file ; qemu_log_unlock() must be adapted as well
by checking thread_file which is always equal to NULL for the main thread.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 util/log.c | 49 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/util/log.c b/util/log.c
index e1c2535cfcd2..0fa23729c78c 100644
--- a/util/log.c
+++ b/util/log.c
@@ -82,6 +82,11 @@ static int log_thread_id(void)
 #endif
 }
 
+static bool is_main_log_thread(void)
+{
+    return log_thread_id() == getpid();
+}
+
 /* Lock/unlock output. */
 
 FILE *qemu_log_trylock(void)
@@ -90,7 +95,8 @@ FILE *qemu_log_trylock(void)
 
     logfile = thread_file;
     if (!logfile) {
-        if (log_per_thread) {
+        /* Main thread to use the global file only */
+        if (log_per_thread && !is_main_log_thread()) {
             g_autofree char *filename
                 = g_strdup_printf(global_filename, log_thread_id());
             logfile = fopen(filename, "w");
@@ -124,7 +130,7 @@ void qemu_log_unlock(FILE *logfile)
     if (logfile) {
         fflush(logfile);
         qemu_funlockfile(logfile);
-        if (!log_per_thread) {
+        if (!thread_file) {
             rcu_read_unlock();
         }
     }
@@ -253,16 +259,21 @@ static bool qemu_set_log_internal(const char *filename, bool changed_name,
 #endif
     qemu_loglevel = log_flags;
 
-    /*
-     * In all cases we only log if qemu_loglevel is set.
-     * Also:
-     *   If per-thread, open the file for each thread in qemu_log_lock.
-     *   If not daemonized we will always log either to stderr
-     *     or to a file (if there is a filename).
-     *   If we are daemonized, we will only log if there is a filename.
-     */
     daemonized = is_daemonized();
-    need_to_open_file = log_flags && !per_thread && (!daemonized || filename);
+    need_to_open_file = false;
+    if (!daemonized) {
+        /*
+         * If not daemonized we only log if qemu_loglevel is set, either to
+         * stderr or to a file (if there is a filename).
+         * If per-thread, open the file for each thread in qemu_log_trylock().
+         */
+        need_to_open_file = qemu_loglevel && !log_per_thread;
+    } else {
+        /*
+         * If we are daemonized, we will only log if there is a filename.
+         */
+        need_to_open_file = filename != NULL;
+    }
 
     if (logfile && (!need_to_open_file || changed_name)) {
         qatomic_rcu_set(&global_file, NULL);
@@ -276,10 +287,22 @@ static bool qemu_set_log_internal(const char *filename, bool changed_name,
 
     if (!logfile && need_to_open_file) {
         if (filename) {
-            logfile = fopen(filename, log_append ? "a" : "w");
+            g_autofree char *fname = NULL;
+
+            /*
+             * If per-thread, filename contains a single %d that should be
+             * converted.
+             */
+            if (per_thread) {
+                fname = g_strdup_printf(filename, getpid());
+            } else {
+                fname = g_strdup(filename);
+            }
+
+            logfile = fopen(fname, log_append ? "a" : "w");
             if (!logfile) {
                 error_setg_errno(errp, errno, "Error opening logfile %s",
-                                 filename);
+                                 fname);
                 return false;
             }
             /* In case we are a daemon redirect stderr to logfile */
-- 
2.37.3



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

* Re: [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  2022-10-19 15:16 ` [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall Greg Kurz
@ 2022-10-19 15:57   ` Daniel P. Berrangé
  2022-10-20  8:40     ` Greg Kurz
  2022-10-20 10:39     ` Paolo Bonzini
  0 siblings, 2 replies; 14+ messages in thread
From: Daniel P. Berrangé @ 2022-10-19 15:57 UTC (permalink / raw)
  To: Greg Kurz; +Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini

On Wed, Oct 19, 2022 at 05:16:50PM +0200, Greg Kurz wrote:
> A subsequent patch needs to be able to differentiate the main QEMU
> thread from other threads. An obvious way to do so is to compare
> log_thread_id() and getpid(), based on the fact that they are equal
> for the main thread on systems that have the gettid() syscall (e.g.
> linux).
> 
> Adapt the fallback code for systems without gettid() to provide the
> same assumption.
> 
> Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Greg Kurz <groug@kaod.org>
> ---
>  util/log.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/util/log.c b/util/log.c
> index d6eb0378c3a3..e1c2535cfcd2 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -72,8 +72,13 @@ static int log_thread_id(void)
>  #elif defined(SYS_gettid)
>      return syscall(SYS_gettid);
>  #else
> +    static __thread int my_id = -1;
>      static int counter;
> -    return qatomic_fetch_inc(&counter);
> +
> +    if (my_id == -1) {
> +        my_id = getpid() + qatomic_fetch_inc(&counter);
> +    }
> +    return my_id;

This doesn't look safe for linux-user when we fork, but don't exec.

The getpid() will change after the fork, but counter won't be
reset, so a thread in the parent could clash with a thread
in the forked child.

I feel like if we want to check for the main thread, we should
be using pthread_self(), and compare result against the value
cached from main. Or cache in a __constructor__ function in
log.c to keep it isolated from main().


With 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] 14+ messages in thread

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-19 15:16 ` [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized Greg Kurz
@ 2022-10-20  2:21   ` Richard Henderson
  2022-10-20  9:49     ` Greg Kurz
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Henderson @ 2022-10-20  2:21 UTC (permalink / raw)
  To: Greg Kurz, qemu-devel
  Cc: Alex Bennée, Daniel P . Berrangé, Paolo Bonzini

On 10/20/22 01:16, Greg Kurz wrote:
> When QEMU is started with `-daemonize`, all stdio descriptors get
> redirected to `/dev/null`. This basically means that anything
> printed with error_report() and friends is lost.
> 
> One could hope that passing `-D ${logfile}` would cause the messages
> to go to `${logfile}`, as the documentation tends to suggest:
> 
>        -D logfile
>                Output log in logfile instead of to stderr
> 
> Unfortunately, `-D` belongs to the logging framework and it only
> does this redirection if some log item is also enabled with `-d`
> or if QEMU was configured with `--enable-trace-backend=log`. A
> typical production setup doesn't do tracing or fine-grain
> debugging but it certainly needs to collect errors.
> 
> Ignore the check on enabled log items when QEMU is daemonized. Previous
> behaviour is retained for the non-daemonized case. The logic is unrolled
> as an `if` for better readability. Since qemu_set_log_internal() caches
> the final log level and the per-thread property in global variables, it
> seems more correct to check these instead of intermediary local variables.
> 
> Special care is needed for the `-D ${logfile} -d tid` case : `${logfile}`
> is expected to be a template that contains exactly one `%d` that should be
> expanded to a PID or TID. The logic in qemu_log_trylock() already takes
> care of that for per-thread logs. Do it as well for the QEMU main thread
> when opening the file.

I don't understand why daemonize changes -d tid at all.
If there's a bug there, please separate it out.

I don't understand the is_main_log_thread checks.
Why is the main thread special?

> -    /*
> -     * In all cases we only log if qemu_loglevel is set.
> -     * Also:
> -     *   If per-thread, open the file for each thread in qemu_log_lock.
> -     *   If not daemonized we will always log either to stderr
> -     *     or to a file (if there is a filename).
> -     *   If we are daemonized, we will only log if there is a filename.
> -     */
>       daemonized = is_daemonized();
> -    need_to_open_file = log_flags && !per_thread && (!daemonized || filename);
> +    need_to_open_file = false;
> +    if (!daemonized) {
> +        /*
> +         * If not daemonized we only log if qemu_loglevel is set, either to
> +         * stderr or to a file (if there is a filename).
> +         * If per-thread, open the file for each thread in qemu_log_trylock().
> +         */
> +        need_to_open_file = qemu_loglevel && !log_per_thread;
> +    } else {
> +        /*
> +         * If we are daemonized, we will only log if there is a filename.
> +         */
> +        need_to_open_file = filename != NULL;
> +    }

I would have thought that this was the only change required -- ignoring qemu_loglevel when 
daemonized.


r~


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

* Re: [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  2022-10-19 15:57   ` Daniel P. Berrangé
@ 2022-10-20  8:40     ` Greg Kurz
  2022-10-20 10:39     ` Paolo Bonzini
  1 sibling, 0 replies; 14+ messages in thread
From: Greg Kurz @ 2022-10-20  8:40 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini

On Wed, 19 Oct 2022 16:57:54 +0100
Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Wed, Oct 19, 2022 at 05:16:50PM +0200, Greg Kurz wrote:
> > A subsequent patch needs to be able to differentiate the main QEMU
> > thread from other threads. An obvious way to do so is to compare
> > log_thread_id() and getpid(), based on the fact that they are equal
> > for the main thread on systems that have the gettid() syscall (e.g.
> > linux).
> > 
> > Adapt the fallback code for systems without gettid() to provide the
> > same assumption.
> > 
> > Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Greg Kurz <groug@kaod.org>
> > ---
> >  util/log.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/util/log.c b/util/log.c
> > index d6eb0378c3a3..e1c2535cfcd2 100644
> > --- a/util/log.c
> > +++ b/util/log.c
> > @@ -72,8 +72,13 @@ static int log_thread_id(void)
> >  #elif defined(SYS_gettid)
> >      return syscall(SYS_gettid);
> >  #else
> > +    static __thread int my_id = -1;
> >      static int counter;
> > -    return qatomic_fetch_inc(&counter);
> > +
> > +    if (my_id == -1) {
> > +        my_id = getpid() + qatomic_fetch_inc(&counter);
> > +    }
> > +    return my_id;
> 
> This doesn't look safe for linux-user when we fork, but don't exec.
> 

... which is a "dangerous" situation if the parent is already
multi-threaded at fork() time. The child thread must only call
async-signal-safe functions and...


> The getpid() will change after the fork, but counter won't be
> reset, so a thread in the parent could clash with a thread
> in the forked child.
> 

... pthread_create() isn't one AFAIK. This case has undefined
behavior.

Anyway, no matter what we do, even with a regular fork+exec pattern,
log_thread_id() no longer guarantees unique values for all threads
that could be running concurrently (unlike gettid() or counter++),
e.g. 
- parent process with pid A and one extra thread
  => parent uses thread ids A and A+1
- fork child process with pid B == A+1
- child execs
  => child uses thread id A+1

> I feel like if we want to check for the main thread, we should
> be using pthread_self(), and compare result against the value
> cached from main. Or cache in a __constructor__ function in
> log.c to keep it isolated from main().
> 

Hmm... pthread_self() is only guaranteed to be unique within
a process. It doesn't look safe either to compare results
of pthread_self() from different process contexts.

> 
> With regards,
> Daniel

Thanks for bringing this corner case up ! It highlights that
I should definitely go for another approach that doesn't
require to check for the main thread at all.

Cheers,

--
Greg


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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-20  2:21   ` Richard Henderson
@ 2022-10-20  9:49     ` Greg Kurz
  2022-10-20  9:58       ` Daniel P. Berrangé
  0 siblings, 1 reply; 14+ messages in thread
From: Greg Kurz @ 2022-10-20  9:49 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Alex Bennée, Daniel P . Berrangé, Paolo Bonzini

On Thu, 20 Oct 2022 12:21:27 +1000
Richard Henderson <richard.henderson@linaro.org> wrote:

> On 10/20/22 01:16, Greg Kurz wrote:
> > When QEMU is started with `-daemonize`, all stdio descriptors get
> > redirected to `/dev/null`. This basically means that anything
> > printed with error_report() and friends is lost.
> > 
> > One could hope that passing `-D ${logfile}` would cause the messages
> > to go to `${logfile}`, as the documentation tends to suggest:
> > 
> >        -D logfile
> >                Output log in logfile instead of to stderr
> > 
> > Unfortunately, `-D` belongs to the logging framework and it only
> > does this redirection if some log item is also enabled with `-d`
> > or if QEMU was configured with `--enable-trace-backend=log`. A
> > typical production setup doesn't do tracing or fine-grain
> > debugging but it certainly needs to collect errors.
> > 
> > Ignore the check on enabled log items when QEMU is daemonized. Previous
> > behaviour is retained for the non-daemonized case. The logic is unrolled
> > as an `if` for better readability. Since qemu_set_log_internal() caches
> > the final log level and the per-thread property in global variables, it
> > seems more correct to check these instead of intermediary local variables.
> > 
> > Special care is needed for the `-D ${logfile} -d tid` case : `${logfile}`
> > is expected to be a template that contains exactly one `%d` that should be
> > expanded to a PID or TID. The logic in qemu_log_trylock() already takes
> > care of that for per-thread logs. Do it as well for the QEMU main thread
> > when opening the file.
> 
> I don't understand why daemonize changes -d tid at all.
> If there's a bug there, please separate it out.
> 
> I don't understand the is_main_log_thread checks.
> Why is the main thread special?
> 

The current code base either opens a per-thread file in
qemu_log_trylock() when -d tid is enabled, or only a
single global file in qemu_log_set_internal() in the
opposite case.

The goal of this patch is to go through the `In case we
are a daemon redirect stderr to logfile` logic, so that
other users of stderr, aka. error_report(), can benefit
from it as well. Since this is only done for the global
file, the logic was changed to : _main_ thread to always
use the global file and other threads to use the per-thread
file.

I now realize how terrible a choice this is. It violates
the current logic too much and brings new problems like
"how to identify the main thread"...

> > -    /*
> > -     * In all cases we only log if qemu_loglevel is set.
> > -     * Also:
> > -     *   If per-thread, open the file for each thread in qemu_log_lock.
> > -     *   If not daemonized we will always log either to stderr
> > -     *     or to a file (if there is a filename).
> > -     *   If we are daemonized, we will only log if there is a filename.
> > -     */
> >       daemonized = is_daemonized();
> > -    need_to_open_file = log_flags && !per_thread && (!daemonized || filename);
> > +    need_to_open_file = false;
> > +    if (!daemonized) {
> > +        /*
> > +         * If not daemonized we only log if qemu_loglevel is set, either to
> > +         * stderr or to a file (if there is a filename).
> > +         * If per-thread, open the file for each thread in qemu_log_trylock().
> > +         */
> > +        need_to_open_file = qemu_loglevel && !log_per_thread;
> > +    } else {
> > +        /*
> > +         * If we are daemonized, we will only log if there is a filename.
> > +         */
> > +        need_to_open_file = filename != NULL;
> > +    }
> 
> I would have thought that this was the only change required -- ignoring qemu_loglevel when 
> daemonized.
> 

I was thinking the same at first, but this ended up in the
global file being open with a filename containing a '%d'...
I chose the direction of doing the g_strdup_printf() trick
for the global file as well but then I had to make sure
that qemu_log_trylock() wouldn't try later to open the same
file, hence the _main_ thread check...

The question is actually : where stderr should point to in
the '-daemonize -D foo%d.log -d tid` case ?

> 

> r~



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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-20  9:49     ` Greg Kurz
@ 2022-10-20  9:58       ` Daniel P. Berrangé
  2022-10-20 10:52         ` Paolo Bonzini
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel P. Berrangé @ 2022-10-20  9:58 UTC (permalink / raw)
  To: Greg Kurz; +Cc: Richard Henderson, qemu-devel, Alex Bennée, Paolo Bonzini

On Thu, Oct 20, 2022 at 11:49:37AM +0200, Greg Kurz wrote:
> On Thu, 20 Oct 2022 12:21:27 +1000
> Richard Henderson <richard.henderson@linaro.org> wrote:
> 
> > On 10/20/22 01:16, Greg Kurz wrote:
> > 
> > I don't understand why daemonize changes -d tid at all.
> > If there's a bug there, please separate it out.
> > 
> > I don't understand the is_main_log_thread checks.
> > Why is the main thread special?
> > 
> 
> The current code base either opens a per-thread file in
> qemu_log_trylock() when -d tid is enabled, or only a
> single global file in qemu_log_set_internal() in the
> opposite case.
> 
> The goal of this patch is to go through the `In case we
> are a daemon redirect stderr to logfile` logic, so that
> other users of stderr, aka. error_report(), can benefit
> from it as well. Since this is only done for the global
> file, the logic was changed to : _main_ thread to always
> use the global file and other threads to use the per-thread
> file.
> 
> I now realize how terrible a choice this is. It violates
> the current logic too much and brings new problems like
> "how to identify the main thread"...

snip

> > I would have thought that this was the only change required -- ignoring qemu_loglevel when 
> > daemonized.
> > 
> 
> I was thinking the same at first, but this ended up in the
> global file being open with a filename containing a '%d'...
> I chose the direction of doing the g_strdup_printf() trick
> for the global file as well but then I had to make sure
> that qemu_log_trylock() wouldn't try later to open the same
> file, hence the _main_ thread check...
> 
> The question is actually : where stderr should point to in
> the '-daemonize -D foo%d.log -d tid` case ?

I'm tending towards thinking the question is wrong, because
it is imposing semantics on -D that it was never designed to
address.

The '-d' option enables logging in QEMU, primary for things
related to TCG. By default that logging goes to stderr, but
it can be sent to 1 or mnay files, using -D. IOW, -D is NOT
about controlling where stderr/out is connected. It is
about where TCG logging goes.


Separately, IIUC, you found that when using -daemonize any
error_report() messages end up in the void, because stderr
is connected to /dev/null.

This patch is thus attempting to repurpose -D as a way to
say where error_report() messages end up with daemonized,
and this creates the complexity  because -D was never
intended to be a mechanism to control stderr or error_report
output.

If we want to connect stdout/err to something when daemonized
then lets either have a dedicated option for that, or simply
tell apps not to use -daemonize and to take care of daemonzing
themselves, thus having full control over stdout/err. The latter
is what libvirt uses, because we actually want stderr/out on a
pipe, not a file, in order to enforce rollover.

With 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] 14+ messages in thread

* Re: [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  2022-10-19 15:57   ` Daniel P. Berrangé
  2022-10-20  8:40     ` Greg Kurz
@ 2022-10-20 10:39     ` Paolo Bonzini
  2022-10-21 14:08       ` Greg Kurz
  1 sibling, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2022-10-20 10:39 UTC (permalink / raw)
  To: Daniel P. Berrangé, Greg Kurz
  Cc: qemu-devel, Alex Bennée, Richard Henderson

On 10/19/22 17:57, Daniel P. Berrangé wrote:
>> +    if (my_id == -1) {
>> +        my_id = getpid() + qatomic_fetch_inc(&counter);
>> +    }
>> +    return my_id;
> This doesn't look safe for linux-user when we fork, but don't exec.

Linux-user won't ever get here, however bsd-user might.  We should have 
get_thread_id() somewhere in util/, for example

https://github.com/wine-mirror/wine/blob/master/dlls/ntdll/unix/server.c

> The getpid() will change after the fork, but counter won't be
> reset, so a thread in the parent could clash with a thread
> in the forked child.

It might clash even if the counter is reset for that matter.

Paolo



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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-20  9:58       ` Daniel P. Berrangé
@ 2022-10-20 10:52         ` Paolo Bonzini
  2022-10-24  9:44           ` Alex Bennée
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2022-10-20 10:52 UTC (permalink / raw)
  To: Daniel P. Berrangé, Greg Kurz
  Cc: Richard Henderson, qemu-devel, Alex Bennée

On 10/20/22 11:58, Daniel P. Berrangé wrote:
> 
> The '-d' option enables logging in QEMU, primary for things
> related to TCG. By default that logging goes to stderr, but
> it can be sent to 1 or mnay files, using -D. IOW, -D is NOT
> about controlling where stderr/out is connected. It is
> about where TCG logging goes.

(Aside: it's not just TCG logging.  The default tracing backend is also 
printing to -D).

> Separately, IIUC, you found that when using -daemonize any
> error_report() messages end up in the void, because stderr
> is connected to /dev/null.
> 
> This patch is thus attempting to repurpose -D as a way to
> say where error_report() messages end up with daemonized,
> and this creates the complexity  because -D was never
> intended to be a mechanism to control stderr or error_report
> output.

True, but it already does that if "-d" is specified, because "-d" 
*intentionally* reopens stderr when -daemonize is specified.  So I think 
overall the idea of "make -D always open the destination when 
daemonizing" is sound, the only weird thing is the interaction with "-d 
tid" which is fixed if we just replace the fallback case from 
log_thread_id() as in Wine's get_unix_tid() code.  "-d tid" can just be 
forbidden if the platform is not supported by get_unix_tid().

> If we want to connect stdout/err to something when daemonized
> then lets either have a dedicated option for that, or simply
> tell apps not to use -daemonize and to take care of daemonzing
> themselves, thus having full control over stdout/err. The latter
> is what libvirt uses, because we actually want stderr/out on a
> pipe, not a file, in order to enforce rollover.

I would gladly get rid of -daemonize, unfortunately it has many users. 
Adding further complication to it is not beautiful, but overall I think 
Greg's patch does make sense.  In particular I would continue the 
refactoring by moving


             /*
              * If per-thread, filename contains a single %d that should be
              * converted.
              */
             if (per_thread) {
                 fname = g_strdup_printf(filename, getpid());
             } else {
                 fname = g_strdup(filename);
             }

             return fopen(fname, log_append ? "a" : "w");

to a new function that can be used in both qemu_log_trylock() and 
qemu_set_log_internal().  (In fact this refactoring is a bugfix because 
per-thread log files do not currently obey log_append).

Paolo



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

* Re: [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall
  2022-10-20 10:39     ` Paolo Bonzini
@ 2022-10-21 14:08       ` Greg Kurz
  0 siblings, 0 replies; 14+ messages in thread
From: Greg Kurz @ 2022-10-21 14:08 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Daniel P. Berrangé, qemu-devel, Alex Bennée, Richard Henderson

On Thu, 20 Oct 2022 12:39:41 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 10/19/22 17:57, Daniel P. Berrangé wrote:
> >> +    if (my_id == -1) {
> >> +        my_id = getpid() + qatomic_fetch_inc(&counter);
> >> +    }
> >> +    return my_id;
> > This doesn't look safe for linux-user when we fork, but don't exec.
> 
> Linux-user won't ever get here, however bsd-user might.  We should have 
> get_thread_id() somewhere in util/, for example
> 
> https://github.com/wine-mirror/wine/blob/master/dlls/ntdll/unix/server.c
> 

We have qemu_get_thread_id() already :

https://git.qemu.org/?p=qemu.git;a=blob;f=util/oslib-posix.c;h=827a7aadba444cdb128284f5b4ba43934c78c3db;hb=HEAD#l96

> > The getpid() will change after the fork, but counter won't be
> > reset, so a thread in the parent could clash with a thread
> > in the forked child.
> 
> It might clash even if the counter is reset for that matter.
> 

Yes.

> Paolo
> 



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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-20 10:52         ` Paolo Bonzini
@ 2022-10-24  9:44           ` Alex Bennée
  2022-10-25  8:52             ` Greg Kurz
  2022-10-25  9:20             ` Paolo Bonzini
  0 siblings, 2 replies; 14+ messages in thread
From: Alex Bennée @ 2022-10-24  9:44 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Daniel P. Berrangé, Greg Kurz, Richard Henderson, qemu-devel


Paolo Bonzini <pbonzini@redhat.com> writes:

<snip>
>> If we want to connect stdout/err to something when daemonized
>> then lets either have a dedicated option for that, or simply
>> tell apps not to use -daemonize and to take care of daemonzing
>> themselves, thus having full control over stdout/err. The latter
>> is what libvirt uses, because we actually want stderr/out on a
>> pipe, not a file, in order to enforce rollover.
>
> I would gladly get rid of -daemonize, unfortunately it has many users.
> Adding further complication to it is not beautiful, but overall I
> think Greg's patch does make sense.  In particular I would continue
> the refactoring by moving
>
>
>             /*
>              * If per-thread, filename contains a single %d that should be
>              * converted.
>              */
>             if (per_thread) {
>                 fname = g_strdup_printf(filename, getpid());
>             } else {
>                 fname = g_strdup(filename);
>             }
>
>             return fopen(fname, log_append ? "a" : "w");
>
> to a new function that can be used in both qemu_log_trylock() and
> qemu_set_log_internal().  (In fact this refactoring is a bugfix
> because per-thread log files do not currently obey log_append).

What is the use case for log_append. AFAICT it only ever applied if you
did a dynamic set_log. Was it ever really used or should it be dropped
as an excessive complication?

From my point of view appending to an existing per-thread log is just
going to cause confusion.

>
> Paolo


-- 
Alex Bennée


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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-24  9:44           ` Alex Bennée
@ 2022-10-25  8:52             ` Greg Kurz
  2022-10-25  9:20             ` Paolo Bonzini
  1 sibling, 0 replies; 14+ messages in thread
From: Greg Kurz @ 2022-10-25  8:52 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Daniel P. Berrangé , Richard Henderson, qemu-devel

On Mon, 24 Oct 2022 10:44:11 +0100
Alex Bennée <alex.bennee@linaro.org> wrote:

> 
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
> <snip>
> >> If we want to connect stdout/err to something when daemonized
> >> then lets either have a dedicated option for that, or simply
> >> tell apps not to use -daemonize and to take care of daemonzing
> >> themselves, thus having full control over stdout/err. The latter
> >> is what libvirt uses, because we actually want stderr/out on a
> >> pipe, not a file, in order to enforce rollover.
> >
> > I would gladly get rid of -daemonize, unfortunately it has many users.
> > Adding further complication to it is not beautiful, but overall I
> > think Greg's patch does make sense.  In particular I would continue
> > the refactoring by moving
> >
> >
> >             /*
> >              * If per-thread, filename contains a single %d that should be
> >              * converted.
> >              */
> >             if (per_thread) {
> >                 fname = g_strdup_printf(filename, getpid());
> >             } else {
> >                 fname = g_strdup(filename);
> >             }
> >
> >             return fopen(fname, log_append ? "a" : "w");
> >
> > to a new function that can be used in both qemu_log_trylock() and
> > qemu_set_log_internal().  (In fact this refactoring is a bugfix
> > because per-thread log files do not currently obey log_append).
> 
> What is the use case for log_append. AFAICT it only ever applied if you
> did a dynamic set_log. Was it ever really used or should it be dropped
> as an excessive complication?
> 

The use case seems to be able to temporarily disable logging,
which closes the log file, without loosing already logged stuff
when logging is re-enabled. QEMU not overwriting previous logs
from the same run is certainly a legitimate expectation from the
user.

Complexity mostly stems from the fact that the log file gets closed
when doing `log none` from the monitor. The logic is also a bit
inconsistent : initial open ensures that we go with a pristine log
file, but renaming the file from the monitor will gladly append
messages to a pre-existing unrelated file...

> From my point of view appending to an existing per-thread log is just
> going to cause confusion.
> 

... and cause confusion all the same.

I'd rather leave the log file always open, except on renames,
and always open in truncating mode.

> >
> > Paolo
> 
> 



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

* Re: [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized
  2022-10-24  9:44           ` Alex Bennée
  2022-10-25  8:52             ` Greg Kurz
@ 2022-10-25  9:20             ` Paolo Bonzini
  1 sibling, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2022-10-25  9:20 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Daniel P. Berrangé, Greg Kurz, Richard Henderson, qemu-devel

On 10/24/22 11:44, Alex Bennée wrote:
> 
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
> <snip>
>>> If we want to connect stdout/err to something when daemonized
>>> then lets either have a dedicated option for that, or simply
>>> tell apps not to use -daemonize and to take care of daemonzing
>>> themselves, thus having full control over stdout/err. The latter
>>> is what libvirt uses, because we actually want stderr/out on a
>>> pipe, not a file, in order to enforce rollover.
>>
>> I would gladly get rid of -daemonize, unfortunately it has many users.
>> Adding further complication to it is not beautiful, but overall I
>> think Greg's patch does make sense.  In particular I would continue
>> the refactoring by moving
>>
>>
>>              /*
>>               * If per-thread, filename contains a single %d that should be
>>               * converted.
>>               */
>>              if (per_thread) {
>>                  fname = g_strdup_printf(filename, getpid());
>>              } else {
>>                  fname = g_strdup(filename);
>>              }
>>
>>              return fopen(fname, log_append ? "a" : "w");
>>
>> to a new function that can be used in both qemu_log_trylock() and
>> qemu_set_log_internal().  (In fact this refactoring is a bugfix
>> because per-thread log files do not currently obey log_append).
> 
> What is the use case for log_append. AFAICT it only ever applied if you
> did a dynamic set_log. Was it ever really used or should it be dropped
> as an excessive complication?

log_append is used if you turn off the logging, which clears log_flags, 
and then turn it on again.  The usecase is that if you remove the file 
QEMU won't keep writing to a deleted file.  ¯\_(ツ)_/¯

However, it's messy.  In particular after changing the file name 
log_append will be 1 and that makes little sense.  The simplest thing to 
do here is just to not close the file, I sent a patch for that.

Paolo

>  From my point of view appending to an existing per-thread log is just
> going to cause confusion.
> 
>>
>> Paolo
> 
> 



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

end of thread, other threads:[~2022-10-25  9:21 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-19 15:16 [PATCH v2 0/2] util/log: Always send errors to logfile when daemonized Greg Kurz
2022-10-19 15:16 ` [PATCH v2 1/2] util/log: Derive thread id from getpid() on hosts w/o gettid() syscall Greg Kurz
2022-10-19 15:57   ` Daniel P. Berrangé
2022-10-20  8:40     ` Greg Kurz
2022-10-20 10:39     ` Paolo Bonzini
2022-10-21 14:08       ` Greg Kurz
2022-10-19 15:16 ` [PATCH v2 2/2] util/log: Always send errors to logfile when daemonized Greg Kurz
2022-10-20  2:21   ` Richard Henderson
2022-10-20  9:49     ` Greg Kurz
2022-10-20  9:58       ` Daniel P. Berrangé
2022-10-20 10:52         ` Paolo Bonzini
2022-10-24  9:44           ` Alex Bennée
2022-10-25  8:52             ` Greg Kurz
2022-10-25  9:20             ` Paolo Bonzini

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.