All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output
@ 2014-03-13  9:41 Stefan Hajnoczi
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 1/2] tests: show the name of each executing qtest Stefan Hajnoczi
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-13  9:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Andreas Faerber, Anthony Liguori, Marcel Apfelbaum

These patches stem from the Marcel's discussion about qtest_init() failures.
He posted the qtest_init() deadlock fix and I was picky about how to fix two
other issues, so here are the patches.

Stefan Hajnoczi (2):
  tests: show the name of each executing qtest
  qtest: fix crash if SIGABRT during qtest_init()

 tests/Makefile   | 7 +++++--
 tests/libqtest.c | 3 ++-
 tests/libqtest.h | 4 +---
 3 files changed, 8 insertions(+), 6 deletions(-)

-- 
1.8.5.3

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

* [Qemu-devel] [PATCH 1/2] tests: show the name of each executing qtest
  2014-03-13  9:41 [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Stefan Hajnoczi
@ 2014-03-13  9:41 ` Stefan Hajnoczi
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
  2014-03-13 11:07 ` [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Marcel Apfelbaum
  2 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-13  9:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Andreas Faerber, Anthony Liguori, Marcel Apfelbaum

When a qtest fails only the assertion failure is printed but you do not
know which qtest binary was running:

  GTESTER check-qtest-x86_64
  main-loop: WARNING: I/O thread spun for 1000 iterations
  blkdebug: Suspended request 'A'
  blkdebug: Resuming request 'A'

check-qtest-x86_64 is actually a make target and not a gtester binary.
The make target includes over 20 separate qtest binaries.

The name of each executing qtest binary should be displayed:

  GTESTER tests/fdc-test
  main-loop: WARNING: I/O thread spun for 1000 iterations
  GTESTER tests/ide-test
  blkdebug: Suspended request 'A'
  blkdebug: Resuming request 'A'

This makes it easy to identify the failing test.

I tried out different ways of displaying qtest binary names.  This patch
implements the best (working) approach I found.  It generates a long
shell command joined with && to execute each qtest binary and print its
name.

This solution is ugly because it doesn't reuse quiet-command.  Maybe a
GNU Make guru will be able to use $(eval) to solve this, but I ended up
with a mix of shell and $(foreach).

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/Makefile | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/tests/Makefile b/tests/Makefile
index b17d41e..d80112a 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -281,9 +281,12 @@ GCOV_OPTIONS = -n $(if $(V),-f,)
 .PHONY: $(patsubst %, check-qtest-%, $(QTEST_TARGETS))
 $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
 	$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
-	$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
+	@true $(foreach qtest-binary, $(check-qtest-$*-y), \
+		&& echo "GTESTER $(qtest-binary)" && \
+		QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
 		MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
-		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
+		gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(qtest-binary) \
+	)
 	$(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y); do \
 	  echo Gcov report for $$f:;\
 	  $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
-- 
1.8.5.3

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

* [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-13  9:41 [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Stefan Hajnoczi
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 1/2] tests: show the name of each executing qtest Stefan Hajnoczi
@ 2014-03-13  9:41 ` Stefan Hajnoczi
  2014-03-13 11:07   ` Marcel Apfelbaum
                     ` (2 more replies)
  2014-03-13 11:07 ` [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Marcel Apfelbaum
  2 siblings, 3 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-13  9:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Andreas Faerber, Anthony Liguori, Marcel Apfelbaum

If an assertion fails during qtest_init() the SIGABRT handler is
invoked.  This is the correct behavior since we need to kill the QEMU
process to avoid leaking it when the test dies.

The global_qtest pointer used by the SIGABRT handler is currently only
assigned after qtest_init() returns.  This results in a segfault if an
assertion failure occurs during qtest_init().

Move global_qtest assignment inside qtest_init().  Not pretty but let's
face it - the signal handler dependeds on global state.

Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tests/libqtest.c | 3 ++-
 tests/libqtest.h | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/tests/libqtest.c b/tests/libqtest.c
index c9e78aa..f387662 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
     qemu_binary = getenv("QTEST_QEMU_BINARY");
     g_assert(qemu_binary != NULL);
 
-    s = g_malloc(sizeof(*s));
+    global_qtest = s = g_malloc(sizeof(*s));
 
     socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
     qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
@@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
 void qtest_quit(QTestState *s)
 {
     sigaction(SIGABRT, &s->sigact_old, NULL);
+    global_qtest = NULL;
 
     kill_qemu(s);
     close(s->fd);
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 9deebdc..7e23a4e 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
  */
 static inline QTestState *qtest_start(const char *args)
 {
-    global_qtest = qtest_init(args);
-    return global_qtest;
+    return qtest_init(args);
 }
 
 /**
@@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
 static inline void qtest_end(void)
 {
     qtest_quit(global_qtest);
-    global_qtest = NULL;
 }
 
 /**
-- 
1.8.5.3

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
@ 2014-03-13 11:07   ` Marcel Apfelbaum
  2014-03-13 12:58     ` Stefan Hajnoczi
  2014-03-13 20:10   ` Andreas Färber
  2014-03-27 13:09   ` Markus Armbruster
  2 siblings, 1 reply; 14+ messages in thread
From: Marcel Apfelbaum @ 2014-03-13 11:07 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel, Anthony Liguori, Andreas Faerber

On Thu, 2014-03-13 at 10:41 +0100, Stefan Hajnoczi wrote:
> If an assertion fails during qtest_init() the SIGABRT handler is
> invoked.  This is the correct behavior since we need to kill the QEMU
> process to avoid leaking it when the test dies.
> 
> The global_qtest pointer used by the SIGABRT handler is currently only
> assigned after qtest_init() returns.  This results in a segfault if an
> assertion failure occurs during qtest_init().
> 
> Move global_qtest assignment inside qtest_init().  Not pretty but let's
> face it - the signal handler dependeds on global state.
Looks OK to me, but it seems that it is symmetrical with my
patch: Mine checked for global_qtest that is not null (not hiding anything :()
and yours increases global_qtest's scope.

I understand why you preferred it this way, to ensure the QEMU instance
is killed, but as I stated before, from my point of view
qtest_init aborted <=> the qemu machine exited because of on error.
(but I might be wrong)

Thanks,
Marcel

> 
> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  tests/libqtest.c | 3 ++-
>  tests/libqtest.h | 4 +---
>  2 files changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/tests/libqtest.c b/tests/libqtest.c
> index c9e78aa..f387662 100644
> --- a/tests/libqtest.c
> +++ b/tests/libqtest.c
> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>      g_assert(qemu_binary != NULL);
>  
> -    s = g_malloc(sizeof(*s));
> +    global_qtest = s = g_malloc(sizeof(*s));
>  
>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>  void qtest_quit(QTestState *s)
>  {
>      sigaction(SIGABRT, &s->sigact_old, NULL);
> +    global_qtest = NULL;
>  
>      kill_qemu(s);
>      close(s->fd);
> diff --git a/tests/libqtest.h b/tests/libqtest.h
> index 9deebdc..7e23a4e 100644
> --- a/tests/libqtest.h
> +++ b/tests/libqtest.h
> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>   */
>  static inline QTestState *qtest_start(const char *args)
>  {
> -    global_qtest = qtest_init(args);
> -    return global_qtest;
> +    return qtest_init(args);
>  }
>  
>  /**
> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>  static inline void qtest_end(void)
>  {
>      qtest_quit(global_qtest);
> -    global_qtest = NULL;
>  }
>  
>  /**

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

* Re: [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output
  2014-03-13  9:41 [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Stefan Hajnoczi
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 1/2] tests: show the name of each executing qtest Stefan Hajnoczi
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
@ 2014-03-13 11:07 ` Marcel Apfelbaum
  2 siblings, 0 replies; 14+ messages in thread
From: Marcel Apfelbaum @ 2014-03-13 11:07 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel, Anthony Liguori, Andreas Faerber

On Thu, 2014-03-13 at 10:41 +0100, Stefan Hajnoczi wrote:
> These patches stem from the Marcel's discussion about qtest_init() failures.
> He posted the qtest_init() deadlock fix and I was picky about how to fix two
> other issues, so here are the patches.

Tested-by: Marcel Apfelbaum <marcel.a@redhat.com>

> 
> Stefan Hajnoczi (2):
>   tests: show the name of each executing qtest
>   qtest: fix crash if SIGABRT during qtest_init()
> 
>  tests/Makefile   | 7 +++++--
>  tests/libqtest.c | 3 ++-
>  tests/libqtest.h | 4 +---
>  3 files changed, 8 insertions(+), 6 deletions(-)
> 

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-13 11:07   ` Marcel Apfelbaum
@ 2014-03-13 12:58     ` Stefan Hajnoczi
  0 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-13 12:58 UTC (permalink / raw)
  To: Marcel Apfelbaum; +Cc: qemu-devel, Anthony Liguori, Andreas Faerber

On Thu, Mar 13, 2014 at 01:07:05PM +0200, Marcel Apfelbaum wrote:
> On Thu, 2014-03-13 at 10:41 +0100, Stefan Hajnoczi wrote:
> > If an assertion fails during qtest_init() the SIGABRT handler is
> > invoked.  This is the correct behavior since we need to kill the QEMU
> > process to avoid leaking it when the test dies.
> > 
> > The global_qtest pointer used by the SIGABRT handler is currently only
> > assigned after qtest_init() returns.  This results in a segfault if an
> > assertion failure occurs during qtest_init().
> > 
> > Move global_qtest assignment inside qtest_init().  Not pretty but let's
> > face it - the signal handler dependeds on global state.
> Looks OK to me, but it seems that it is symmetrical with my
> patch: Mine checked for global_qtest that is not null (not hiding anything :()
> and yours increases global_qtest's scope.
> 
> I understand why you preferred it this way, to ensure the QEMU instance
> is killed, but as I stated before, from my point of view
> qtest_init aborted <=> the qemu machine exited because of on error.
> (but I might be wrong)

Think about this case:

If we hit an assertion failure in qtest_init() because of socket errors
(e.g. QEMU ran for a little bit but closed the socket while we were
negotiating), then we *do* need to kill the QEMU process.

Stefan

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
  2014-03-13 11:07   ` Marcel Apfelbaum
@ 2014-03-13 20:10   ` Andreas Färber
  2014-03-27 13:09   ` Markus Armbruster
  2 siblings, 0 replies; 14+ messages in thread
From: Andreas Färber @ 2014-03-13 20:10 UTC (permalink / raw)
  To: Stefan Hajnoczi, qemu-devel, Marcel Apfelbaum; +Cc: Anthony Liguori

Am 13.03.2014 10:41, schrieb Stefan Hajnoczi:
> If an assertion fails during qtest_init() the SIGABRT handler is
> invoked.  This is the correct behavior since we need to kill the QEMU
> process to avoid leaking it when the test dies.
> 
> The global_qtest pointer used by the SIGABRT handler is currently only
> assigned after qtest_init() returns.  This results in a segfault if an
> assertion failure occurs during qtest_init().
> 
> Move global_qtest assignment inside qtest_init().  Not pretty but let's
> face it - the signal handler dependeds on global state.
> 
> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  tests/libqtest.c | 3 ++-
>  tests/libqtest.h | 4 +---
>  2 files changed, 3 insertions(+), 4 deletions(-)

Thanks, applied to qom-next (with typo fix):
https://github.com/afaerber/qemu-cpu/commits/qom-next

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
  2014-03-13 11:07   ` Marcel Apfelbaum
  2014-03-13 20:10   ` Andreas Färber
@ 2014-03-27 13:09   ` Markus Armbruster
  2014-03-27 13:12     ` Andreas Färber
  2 siblings, 1 reply; 14+ messages in thread
From: Markus Armbruster @ 2014-03-27 13:09 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Marcel Apfelbaum, qemu-devel, Anthony Liguori, Andreas Faerber

Reply after commit, sorry.

Stefan Hajnoczi <stefanha@redhat.com> writes:

> If an assertion fails during qtest_init() the SIGABRT handler is
> invoked.  This is the correct behavior since we need to kill the QEMU
> process to avoid leaking it when the test dies.
>
> The global_qtest pointer used by the SIGABRT handler is currently only
> assigned after qtest_init() returns.  This results in a segfault if an
> assertion failure occurs during qtest_init().
>
> Move global_qtest assignment inside qtest_init().  Not pretty but let's
> face it - the signal handler dependeds on global state.
>
> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  tests/libqtest.c | 3 ++-
>  tests/libqtest.h | 4 +---
>  2 files changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/tests/libqtest.c b/tests/libqtest.c
> index c9e78aa..f387662 100644
> --- a/tests/libqtest.c
> +++ b/tests/libqtest.c
> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>      g_assert(qemu_binary != NULL);
>  
> -    s = g_malloc(sizeof(*s));
> +    global_qtest = s = g_malloc(sizeof(*s));
>  
>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>  void qtest_quit(QTestState *s)
>  {
>      sigaction(SIGABRT, &s->sigact_old, NULL);
> +    global_qtest = NULL;
>  
>      kill_qemu(s);
>      close(s->fd);
> diff --git a/tests/libqtest.h b/tests/libqtest.h
> index 9deebdc..7e23a4e 100644
> --- a/tests/libqtest.h
> +++ b/tests/libqtest.h
> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>   */
>  static inline QTestState *qtest_start(const char *args)
>  {
> -    global_qtest = qtest_init(args);
> -    return global_qtest;
> +    return qtest_init(args);
>  }
>  
>  /**
> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>  static inline void qtest_end(void)
>  {
>      qtest_quit(global_qtest);
> -    global_qtest = NULL;
>  }
>  
>  /**

Before this patch, the libqtest API could theoretically support multiple
simultaneous instances of QTestState.  This patch kills that option,
doesn't it?

If yes: fine with me, we don't need it anyway.  But shouldn't we clean
up the API then?  It typically provides a function taking a QTestState
parameter, and a wrapper that passes global_qtest.  If global_qtest is
the only QTestState we can have, having the former function is
pointless.

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 13:09   ` Markus Armbruster
@ 2014-03-27 13:12     ` Andreas Färber
  2014-03-27 13:34       ` Marcel Apfelbaum
  2014-03-27 13:36       ` Stefan Hajnoczi
  0 siblings, 2 replies; 14+ messages in thread
From: Andreas Färber @ 2014-03-27 13:12 UTC (permalink / raw)
  To: Markus Armbruster, Stefan Hajnoczi
  Cc: qemu-devel, Anthony Liguori, Marcel Apfelbaum

Am 27.03.2014 14:09, schrieb Markus Armbruster:
> Reply after commit, sorry.
> 
> Stefan Hajnoczi <stefanha@redhat.com> writes:
> 
>> If an assertion fails during qtest_init() the SIGABRT handler is
>> invoked.  This is the correct behavior since we need to kill the QEMU
>> process to avoid leaking it when the test dies.
>>
>> The global_qtest pointer used by the SIGABRT handler is currently only
>> assigned after qtest_init() returns.  This results in a segfault if an
>> assertion failure occurs during qtest_init().
>>
>> Move global_qtest assignment inside qtest_init().  Not pretty but let's
>> face it - the signal handler dependeds on global state.
>>
>> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
>> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>> ---
>>  tests/libqtest.c | 3 ++-
>>  tests/libqtest.h | 4 +---
>>  2 files changed, 3 insertions(+), 4 deletions(-)
>>
>> diff --git a/tests/libqtest.c b/tests/libqtest.c
>> index c9e78aa..f387662 100644
>> --- a/tests/libqtest.c
>> +++ b/tests/libqtest.c
>> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>>      g_assert(qemu_binary != NULL);
>>  
>> -    s = g_malloc(sizeof(*s));
>> +    global_qtest = s = g_malloc(sizeof(*s));
>>  
>>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
>> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>>  void qtest_quit(QTestState *s)
>>  {
>>      sigaction(SIGABRT, &s->sigact_old, NULL);
>> +    global_qtest = NULL;
>>  
>>      kill_qemu(s);
>>      close(s->fd);
>> diff --git a/tests/libqtest.h b/tests/libqtest.h
>> index 9deebdc..7e23a4e 100644
>> --- a/tests/libqtest.h
>> +++ b/tests/libqtest.h
>> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>>   */
>>  static inline QTestState *qtest_start(const char *args)
>>  {
>> -    global_qtest = qtest_init(args);
>> -    return global_qtest;
>> +    return qtest_init(args);
>>  }
>>  
>>  /**
>> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>>  static inline void qtest_end(void)
>>  {
>>      qtest_quit(global_qtest);
>> -    global_qtest = NULL;
>>  }
>>  
>>  /**
> 
> Before this patch, the libqtest API could theoretically support multiple
> simultaneous instances of QTestState.  This patch kills that option,
> doesn't it?

Ouch, I thought I had looked out for that...

> 
> If yes: fine with me, we don't need it anyway.

We do. Migration and ivshmem are examples that need two machines - might
explain why my ivshmem-test was behaving unexpectedly.

Apart from reverting, what are our options?

Regards,
Andreas

>  But shouldn't we clean
> up the API then?  It typically provides a function taking a QTestState
> parameter, and a wrapper that passes global_qtest.  If global_qtest is
> the only QTestState we can have, having the former function is
> pointless.
> 


-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 13:12     ` Andreas Färber
@ 2014-03-27 13:34       ` Marcel Apfelbaum
  2014-03-27 13:37         ` Stefan Hajnoczi
  2014-03-27 13:36       ` Stefan Hajnoczi
  1 sibling, 1 reply; 14+ messages in thread
From: Marcel Apfelbaum @ 2014-03-27 13:34 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Anthony Liguori, Markus Armbruster, Stefan Hajnoczi, qemu-devel

On Thu, 2014-03-27 at 14:12 +0100, Andreas Färber wrote:
> Am 27.03.2014 14:09, schrieb Markus Armbruster:
> > Reply after commit, sorry.
> > 
> > Stefan Hajnoczi <stefanha@redhat.com> writes:
> > 
> >> If an assertion fails during qtest_init() the SIGABRT handler is
> >> invoked.  This is the correct behavior since we need to kill the QEMU
> >> process to avoid leaking it when the test dies.
> >>
> >> The global_qtest pointer used by the SIGABRT handler is currently only
> >> assigned after qtest_init() returns.  This results in a segfault if an
> >> assertion failure occurs during qtest_init().
> >>
> >> Move global_qtest assignment inside qtest_init().  Not pretty but let's
> >> face it - the signal handler dependeds on global state.
> >>
> >> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
> >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> >> ---
> >>  tests/libqtest.c | 3 ++-
> >>  tests/libqtest.h | 4 +---
> >>  2 files changed, 3 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/tests/libqtest.c b/tests/libqtest.c
> >> index c9e78aa..f387662 100644
> >> --- a/tests/libqtest.c
> >> +++ b/tests/libqtest.c
> >> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
> >>      qemu_binary = getenv("QTEST_QEMU_BINARY");
> >>      g_assert(qemu_binary != NULL);
> >>  
> >> -    s = g_malloc(sizeof(*s));
> >> +    global_qtest = s = g_malloc(sizeof(*s));
> >>  
> >>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
> >>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
> >> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
> >>  void qtest_quit(QTestState *s)
> >>  {
> >>      sigaction(SIGABRT, &s->sigact_old, NULL);
> >> +    global_qtest = NULL;
> >>  
> >>      kill_qemu(s);
> >>      close(s->fd);
> >> diff --git a/tests/libqtest.h b/tests/libqtest.h
> >> index 9deebdc..7e23a4e 100644
> >> --- a/tests/libqtest.h
> >> +++ b/tests/libqtest.h
> >> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
> >>   */
> >>  static inline QTestState *qtest_start(const char *args)
> >>  {
> >> -    global_qtest = qtest_init(args);
> >> -    return global_qtest;
> >> +    return qtest_init(args);
> >>  }
> >>  
> >>  /**
> >> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
> >>  static inline void qtest_end(void)
> >>  {
> >>      qtest_quit(global_qtest);
> >> -    global_qtest = NULL;
> >>  }
> >>  
> >>  /**
> > 
> > Before this patch, the libqtest API could theoretically support multiple
> > simultaneous instances of QTestState.  This patch kills that option,
> > doesn't it?
> 
> Ouch, I thought I had looked out for that...
> 
> > 
> > If yes: fine with me, we don't need it anyway.
> 
> We do. Migration and ivshmem are examples that need two machines - might
> explain why my ivshmem-test was behaving unexpectedly.
> 
> Apart from reverting, what are our options?
The problem is in 'kill_qemu' function, which is called from
SIGABRT signal handler.  The later needs to know the QTestState
in order to kill the QEMU process.

Without this patch, kill_qemu will cause a segfault because of:
static void kill_qemu(QTestState *s)
{
    if (s->qemu_pid != -1) {
...
s can be NULL if there is an assert in qtest_init.

I suppose we can find a different approach, like keeping
the qemu_pid(s) in another statically defined struct.
 
Thanks,
Marcel

 
> 
> Regards,
> Andreas
> 
> >  But shouldn't we clean
> > up the API then?  It typically provides a function taking a QTestState
> > parameter, and a wrapper that passes global_qtest.  If global_qtest is
> > the only QTestState we can have, having the former function is
> > pointless.
> > 
> 
> 

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 13:12     ` Andreas Färber
  2014-03-27 13:34       ` Marcel Apfelbaum
@ 2014-03-27 13:36       ` Stefan Hajnoczi
  1 sibling, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-27 13:36 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Marcel Apfelbaum, Anthony Liguori, Markus Armbruster,
	Stefan Hajnoczi, qemu-devel

On Thu, Mar 27, 2014 at 2:12 PM, Andreas Färber <afaerber@suse.de> wrote:
>> Before this patch, the libqtest API could theoretically support multiple
>> simultaneous instances of QTestState.  This patch kills that option,
>> doesn't it?
>
> Ouch, I thought I had looked out for that...
>
>>
>> If yes: fine with me, we don't need it anyway.
>
> We do. Migration and ivshmem are examples that need two machines - might
> explain why my ivshmem-test was behaving unexpectedly.
>
> Apart from reverting, what are our options?

Argh, I wasn't aware some tests run with two separate instances.

We can implement more elaborate error handling, for example an
atexit(3)-style atabort mechanism.  This way, each instance can get
its callback.

Stefan

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 13:34       ` Marcel Apfelbaum
@ 2014-03-27 13:37         ` Stefan Hajnoczi
  2014-03-27 14:02           ` Markus Armbruster
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-27 13:37 UTC (permalink / raw)
  To: Marcel Apfelbaum
  Cc: qemu-devel, Stefan Hajnoczi, Andreas Färber,
	Anthony Liguori, Markus Armbruster

On Thu, Mar 27, 2014 at 2:34 PM, Marcel Apfelbaum <marcel.a@redhat.com> wrote:
> On Thu, 2014-03-27 at 14:12 +0100, Andreas Färber wrote:
>> Am 27.03.2014 14:09, schrieb Markus Armbruster:
>> > Reply after commit, sorry.
>> >
>> > Stefan Hajnoczi <stefanha@redhat.com> writes:
>> >
>> >> If an assertion fails during qtest_init() the SIGABRT handler is
>> >> invoked.  This is the correct behavior since we need to kill the QEMU
>> >> process to avoid leaking it when the test dies.
>> >>
>> >> The global_qtest pointer used by the SIGABRT handler is currently only
>> >> assigned after qtest_init() returns.  This results in a segfault if an
>> >> assertion failure occurs during qtest_init().
>> >>
>> >> Move global_qtest assignment inside qtest_init().  Not pretty but let's
>> >> face it - the signal handler dependeds on global state.
>> >>
>> >> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
>> >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>> >> ---
>> >>  tests/libqtest.c | 3 ++-
>> >>  tests/libqtest.h | 4 +---
>> >>  2 files changed, 3 insertions(+), 4 deletions(-)
>> >>
>> >> diff --git a/tests/libqtest.c b/tests/libqtest.c
>> >> index c9e78aa..f387662 100644
>> >> --- a/tests/libqtest.c
>> >> +++ b/tests/libqtest.c
>> >> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>> >>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>> >>      g_assert(qemu_binary != NULL);
>> >>
>> >> -    s = g_malloc(sizeof(*s));
>> >> +    global_qtest = s = g_malloc(sizeof(*s));
>> >>
>> >>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>> >>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
>> >> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>> >>  void qtest_quit(QTestState *s)
>> >>  {
>> >>      sigaction(SIGABRT, &s->sigact_old, NULL);
>> >> +    global_qtest = NULL;
>> >>
>> >>      kill_qemu(s);
>> >>      close(s->fd);
>> >> diff --git a/tests/libqtest.h b/tests/libqtest.h
>> >> index 9deebdc..7e23a4e 100644
>> >> --- a/tests/libqtest.h
>> >> +++ b/tests/libqtest.h
>> >> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>> >>   */
>> >>  static inline QTestState *qtest_start(const char *args)
>> >>  {
>> >> -    global_qtest = qtest_init(args);
>> >> -    return global_qtest;
>> >> +    return qtest_init(args);
>> >>  }
>> >>
>> >>  /**
>> >> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>> >>  static inline void qtest_end(void)
>> >>  {
>> >>      qtest_quit(global_qtest);
>> >> -    global_qtest = NULL;
>> >>  }
>> >>
>> >>  /**
>> >
>> > Before this patch, the libqtest API could theoretically support multiple
>> > simultaneous instances of QTestState.  This patch kills that option,
>> > doesn't it?
>>
>> Ouch, I thought I had looked out for that...
>>
>> >
>> > If yes: fine with me, we don't need it anyway.
>>
>> We do. Migration and ivshmem are examples that need two machines - might
>> explain why my ivshmem-test was behaving unexpectedly.
>>
>> Apart from reverting, what are our options?
> The problem is in 'kill_qemu' function, which is called from
> SIGABRT signal handler.  The later needs to know the QTestState
> in order to kill the QEMU process.
>
> Without this patch, kill_qemu will cause a segfault because of:
> static void kill_qemu(QTestState *s)
> {
>     if (s->qemu_pid != -1) {
> ...
> s can be NULL if there is an assert in qtest_init.
>
> I suppose we can find a different approach, like keeping
> the qemu_pid(s) in another statically defined struct.

We can keep a global linked list of QEMU pids.

Stefan

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 13:37         ` Stefan Hajnoczi
@ 2014-03-27 14:02           ` Markus Armbruster
  2014-03-27 14:03             ` Stefan Hajnoczi
  0 siblings, 1 reply; 14+ messages in thread
From: Markus Armbruster @ 2014-03-27 14:02 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Andreas Färber, Anthony Liguori, qemu-devel,
	Stefan Hajnoczi, Marcel Apfelbaum

Stefan Hajnoczi <stefanha@gmail.com> writes:

> On Thu, Mar 27, 2014 at 2:34 PM, Marcel Apfelbaum <marcel.a@redhat.com> wrote:
>> On Thu, 2014-03-27 at 14:12 +0100, Andreas Färber wrote:
>>> Am 27.03.2014 14:09, schrieb Markus Armbruster:
>>> > Reply after commit, sorry.
>>> >
>>> > Stefan Hajnoczi <stefanha@redhat.com> writes:
>>> >
>>> >> If an assertion fails during qtest_init() the SIGABRT handler is
>>> >> invoked.  This is the correct behavior since we need to kill the QEMU
>>> >> process to avoid leaking it when the test dies.
>>> >>
>>> >> The global_qtest pointer used by the SIGABRT handler is currently only
>>> >> assigned after qtest_init() returns.  This results in a segfault if an
>>> >> assertion failure occurs during qtest_init().
>>> >>
>>> >> Move global_qtest assignment inside qtest_init().  Not pretty but let's
>>> >> face it - the signal handler dependeds on global state.
>>> >>
>>> >> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
>>> >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>>> >> ---
>>> >>  tests/libqtest.c | 3 ++-
>>> >>  tests/libqtest.h | 4 +---
>>> >>  2 files changed, 3 insertions(+), 4 deletions(-)
>>> >>
>>> >> diff --git a/tests/libqtest.c b/tests/libqtest.c
>>> >> index c9e78aa..f387662 100644
>>> >> --- a/tests/libqtest.c
>>> >> +++ b/tests/libqtest.c
>>> >> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>>> >>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>>> >>      g_assert(qemu_binary != NULL);
>>> >>
>>> >> -    s = g_malloc(sizeof(*s));
>>> >> +    global_qtest = s = g_malloc(sizeof(*s));
>>> >>
>>> >>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>>> >>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
>>> >> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>>> >>  void qtest_quit(QTestState *s)
>>> >>  {
>>> >>      sigaction(SIGABRT, &s->sigact_old, NULL);
>>> >> +    global_qtest = NULL;
>>> >>
>>> >>      kill_qemu(s);
>>> >>      close(s->fd);
>>> >> diff --git a/tests/libqtest.h b/tests/libqtest.h
>>> >> index 9deebdc..7e23a4e 100644
>>> >> --- a/tests/libqtest.h
>>> >> +++ b/tests/libqtest.h
>>> >> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>>> >>   */
>>> >>  static inline QTestState *qtest_start(const char *args)
>>> >>  {
>>> >> -    global_qtest = qtest_init(args);
>>> >> -    return global_qtest;
>>> >> +    return qtest_init(args);
>>> >>  }
>>> >>
>>> >>  /**
>>> >> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>>> >>  static inline void qtest_end(void)
>>> >>  {
>>> >>      qtest_quit(global_qtest);
>>> >> -    global_qtest = NULL;
>>> >>  }
>>> >>
>>> >>  /**
>>> >
>>> > Before this patch, the libqtest API could theoretically support multiple
>>> > simultaneous instances of QTestState.  This patch kills that option,
>>> > doesn't it?
>>>
>>> Ouch, I thought I had looked out for that...
>>>
>>> >
>>> > If yes: fine with me, we don't need it anyway.
>>>
>>> We do. Migration and ivshmem are examples that need two machines - might
>>> explain why my ivshmem-test was behaving unexpectedly.
>>>
>>> Apart from reverting, what are our options?
>> The problem is in 'kill_qemu' function, which is called from
>> SIGABRT signal handler.  The later needs to know the QTestState
>> in order to kill the QEMU process.
>>
>> Without this patch, kill_qemu will cause a segfault because of:
>> static void kill_qemu(QTestState *s)
>> {
>>     if (s->qemu_pid != -1) {
>> ...
>> s can be NULL if there is an assert in qtest_init.
>>
>> I suppose we can find a different approach, like keeping
>> the qemu_pid(s) in another statically defined struct.
>
> We can keep a global linked list of QEMU pids.

What about a global list of QTestState?

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

* Re: [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init()
  2014-03-27 14:02           ` Markus Armbruster
@ 2014-03-27 14:03             ` Stefan Hajnoczi
  0 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2014-03-27 14:03 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Andreas Färber, Anthony Liguori, qemu-devel,
	Stefan Hajnoczi, Marcel Apfelbaum

On Thu, Mar 27, 2014 at 3:02 PM, Markus Armbruster <armbru@redhat.com> wrote:
> Stefan Hajnoczi <stefanha@gmail.com> writes:
>
>> On Thu, Mar 27, 2014 at 2:34 PM, Marcel Apfelbaum <marcel.a@redhat.com> wrote:
>>> On Thu, 2014-03-27 at 14:12 +0100, Andreas Färber wrote:
>>>> Am 27.03.2014 14:09, schrieb Markus Armbruster:
>>>> > Reply after commit, sorry.
>>>> >
>>>> > Stefan Hajnoczi <stefanha@redhat.com> writes:
>>>> >
>>>> >> If an assertion fails during qtest_init() the SIGABRT handler is
>>>> >> invoked.  This is the correct behavior since we need to kill the QEMU
>>>> >> process to avoid leaking it when the test dies.
>>>> >>
>>>> >> The global_qtest pointer used by the SIGABRT handler is currently only
>>>> >> assigned after qtest_init() returns.  This results in a segfault if an
>>>> >> assertion failure occurs during qtest_init().
>>>> >>
>>>> >> Move global_qtest assignment inside qtest_init().  Not pretty but let's
>>>> >> face it - the signal handler dependeds on global state.
>>>> >>
>>>> >> Reported-by: Marcel Apfelbaum <marcel.a@redhat.com>
>>>> >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>>>> >> ---
>>>> >>  tests/libqtest.c | 3 ++-
>>>> >>  tests/libqtest.h | 4 +---
>>>> >>  2 files changed, 3 insertions(+), 4 deletions(-)
>>>> >>
>>>> >> diff --git a/tests/libqtest.c b/tests/libqtest.c
>>>> >> index c9e78aa..f387662 100644
>>>> >> --- a/tests/libqtest.c
>>>> >> +++ b/tests/libqtest.c
>>>> >> @@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
>>>> >>      qemu_binary = getenv("QTEST_QEMU_BINARY");
>>>> >>      g_assert(qemu_binary != NULL);
>>>> >>
>>>> >> -    s = g_malloc(sizeof(*s));
>>>> >> +    global_qtest = s = g_malloc(sizeof(*s));
>>>> >>
>>>> >>      socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>>>> >>      qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
>>>> >> @@ -181,6 +181,7 @@ QTestState *qtest_init(const char *extra_args)
>>>> >>  void qtest_quit(QTestState *s)
>>>> >>  {
>>>> >>      sigaction(SIGABRT, &s->sigact_old, NULL);
>>>> >> +    global_qtest = NULL;
>>>> >>
>>>> >>      kill_qemu(s);
>>>> >>      close(s->fd);
>>>> >> diff --git a/tests/libqtest.h b/tests/libqtest.h
>>>> >> index 9deebdc..7e23a4e 100644
>>>> >> --- a/tests/libqtest.h
>>>> >> +++ b/tests/libqtest.h
>>>> >> @@ -335,8 +335,7 @@ void qtest_add_func(const char *str, void (*fn));
>>>> >>   */
>>>> >>  static inline QTestState *qtest_start(const char *args)
>>>> >>  {
>>>> >> -    global_qtest = qtest_init(args);
>>>> >> -    return global_qtest;
>>>> >> +    return qtest_init(args);
>>>> >>  }
>>>> >>
>>>> >>  /**
>>>> >> @@ -347,7 +346,6 @@ static inline QTestState *qtest_start(const char *args)
>>>> >>  static inline void qtest_end(void)
>>>> >>  {
>>>> >>      qtest_quit(global_qtest);
>>>> >> -    global_qtest = NULL;
>>>> >>  }
>>>> >>
>>>> >>  /**
>>>> >
>>>> > Before this patch, the libqtest API could theoretically support multiple
>>>> > simultaneous instances of QTestState.  This patch kills that option,
>>>> > doesn't it?
>>>>
>>>> Ouch, I thought I had looked out for that...
>>>>
>>>> >
>>>> > If yes: fine with me, we don't need it anyway.
>>>>
>>>> We do. Migration and ivshmem are examples that need two machines - might
>>>> explain why my ivshmem-test was behaving unexpectedly.
>>>>
>>>> Apart from reverting, what are our options?
>>> The problem is in 'kill_qemu' function, which is called from
>>> SIGABRT signal handler.  The later needs to know the QTestState
>>> in order to kill the QEMU process.
>>>
>>> Without this patch, kill_qemu will cause a segfault because of:
>>> static void kill_qemu(QTestState *s)
>>> {
>>>     if (s->qemu_pid != -1) {
>>> ...
>>> s can be NULL if there is an assert in qtest_init.
>>>
>>> I suppose we can find a different approach, like keeping
>>> the qemu_pid(s) in another statically defined struct.
>>
>> We can keep a global linked list of QEMU pids.
>
> What about a global list of QTestState?

Yes, that's exactly what I ended up implementing.  Sending patch.

Stefan

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

end of thread, other threads:[~2014-03-27 14:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-13  9:41 [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Stefan Hajnoczi
2014-03-13  9:41 ` [Qemu-devel] [PATCH 1/2] tests: show the name of each executing qtest Stefan Hajnoczi
2014-03-13  9:41 ` [Qemu-devel] [PATCH 2/2] qtest: fix crash if SIGABRT during qtest_init() Stefan Hajnoczi
2014-03-13 11:07   ` Marcel Apfelbaum
2014-03-13 12:58     ` Stefan Hajnoczi
2014-03-13 20:10   ` Andreas Färber
2014-03-27 13:09   ` Markus Armbruster
2014-03-27 13:12     ` Andreas Färber
2014-03-27 13:34       ` Marcel Apfelbaum
2014-03-27 13:37         ` Stefan Hajnoczi
2014-03-27 14:02           ` Markus Armbruster
2014-03-27 14:03             ` Stefan Hajnoczi
2014-03-27 13:36       ` Stefan Hajnoczi
2014-03-13 11:07 ` [Qemu-devel] [PATCH 0/2] qtest: crash fix and improved "make check" output Marcel Apfelbaum

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.