diff mbox series

[V1,12/32] vl: pause option

Message ID 1596122076-341293-13-git-send-email-steven.sistare@oracle.com (mailing list archive)
State New, archived
Headers show
Series Live Update | expand

Commit Message

Steven Sistare July 30, 2020, 3:14 p.m. UTC
Provide the -pause command-line parameter and the QEMU_PAUSE environment
variable to briefly pause QEMU in main and allow a developer to attach gdb.
Useful when the developer does not invoke QEMU directly, such as when using
libvirt.

Usage:
  qemu -pause <seconds>
  or
  export QEMU_PAUSE=<seconds>

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
---
 qemu-options.hx |  9 +++++++++
 softmmu/vl.c    | 15 ++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

Comments

Eric Blake July 30, 2020, 4:20 p.m. UTC | #1
On 7/30/20 10:14 AM, Steve Sistare wrote:
> Provide the -pause command-line parameter and the QEMU_PAUSE environment
> variable to briefly pause QEMU in main and allow a developer to attach gdb.
> Useful when the developer does not invoke QEMU directly, such as when using
> libvirt.

How would you set this option with libvirt?

It feels like you are trying to reinvent something that is already 
well-documented:

https://www.berrange.com/posts/2011/10/12/debugging-early-startup-of-kvm-with-gdb-when-launched-by-libvirtd/

> 
> Usage:
>    qemu -pause <seconds>
>    or
>    export QEMU_PAUSE=<seconds>
> 
> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
> ---
>   qemu-options.hx |  9 +++++++++
>   softmmu/vl.c    | 15 ++++++++++++++-
>   2 files changed, 23 insertions(+), 1 deletion(-)

> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
>               case QEMU_OPTION_gdb:
>                   add_device_config(DEV_GDB, optarg);
>                   break;
> +            case QEMU_OPTION_pause:
> +                seconds = atoi(optarg);

atoi() cannot detect overflow.  You should never use it in robust 
parsing of untrusted input.
Alex Bennée July 30, 2020, 5:03 p.m. UTC | #2
Steve Sistare <steven.sistare@oracle.com> writes:

> Provide the -pause command-line parameter and the QEMU_PAUSE environment
> variable to briefly pause QEMU in main and allow a developer to attach gdb.
> Useful when the developer does not invoke QEMU directly, such as when using
> libvirt.

How does this differ from -S?

>
> Usage:
>   qemu -pause <seconds>
>   or
>   export QEMU_PAUSE=<seconds>
>
> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
> ---
>  qemu-options.hx |  9 +++++++++
>  softmmu/vl.c    | 15 ++++++++++++++-
>  2 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 708583b..8505cf2 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3668,6 +3668,15 @@ SRST
>      option is experimental.
>  ERST
>  
> +DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
> +    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
> +
> +SRST
> +``--pause secs``
> +    Pause for a number of seconds on entry to main.  Useful for attaching
> +    a debugger after QEMU has been launched by some other entity.
> +ERST
> +

It seems like having an option to race with the debugger is just asking
for trouble.

>  DEF("S", 0, QEMU_OPTION_S, \
>      "-S              freeze CPU at startup (use 'c' to start execution)\n",
>      QEMU_ARCH_ALL)
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 8478778..951994f 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2844,7 +2844,7 @@ static void create_default_memdev(MachineState *ms, const char *path)
>  
>  void qemu_init(int argc, char **argv, char **envp)
>  {
> -    int i;
> +    int i, seconds;
>      int snapshot, linux_boot;
>      const char *initrd_filename;
>      const char *kernel_filename, *kernel_cmdline;
> @@ -2882,6 +2882,13 @@ void qemu_init(int argc, char **argv, char **envp)
>      QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
>      int mem_prealloc = 0; /* force preallocation of physical target memory */
>  
> +    if (getenv("QEMU_PAUSE")) {
> +        seconds = atoi(getenv("QEMU_PAUSE"));
> +        printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
> +               seconds, getpid());
> +        sleep(seconds);
> +    }
> +
>      os_set_line_buffering();
>  
>      error_init(argv[0]);
> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
>              case QEMU_OPTION_gdb:
>                  add_device_config(DEV_GDB, optarg);
>                  break;
> +            case QEMU_OPTION_pause:
> +                seconds = atoi(optarg);
> +                printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
> +                            seconds, getpid());
> +                sleep(seconds);
> +                break;
>              case QEMU_OPTION_L:
>                  if (is_help_option(optarg)) {
>                      list_data_dirs = true;
Steven Sistare July 30, 2020, 6:11 p.m. UTC | #3
On 7/30/2020 12:20 PM, Eric Blake wrote:
> On 7/30/20 10:14 AM, Steve Sistare wrote:
>> Provide the -pause command-line parameter and the QEMU_PAUSE environment
>> variable to briefly pause QEMU in main and allow a developer to attach gdb.
>> Useful when the developer does not invoke QEMU directly, such as when using
>> libvirt.
> 
> How would you set this option with libvirt?

Add -pause in the qemu args in the xml.
 
> It feels like you are trying to reinvent something that is already well-documented:
> 
> https://www.berrange.com/posts/2011/10/12/debugging-early-startup-of-kvm-with-gdb-when-launched-by-libvirtd/

Too many steps to reach BINGO for my taste.  Easier is better.  Also, in our shop we start qemu 
in other ways, such as via services.

These new hooks helped me and my colleagues, and I hope others may also find them useful, 
but if not then we drop them.

>> Usage:
>>    qemu -pause <seconds>
>>    or
>>    export QEMU_PAUSE=<seconds>
>>
>> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
>> ---
>>   qemu-options.hx |  9 +++++++++
>>   softmmu/vl.c    | 15 ++++++++++++++-
>>   2 files changed, 23 insertions(+), 1 deletion(-)
> 
>> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
>>               case QEMU_OPTION_gdb:
>>                   add_device_config(DEV_GDB, optarg);
>>                   break;
>> +            case QEMU_OPTION_pause:
>> +                seconds = atoi(optarg);
> 
> atoi() cannot detect overflow.  You should never use it in robust parsing of untrusted input.

OK.

- Steve
Steven Sistare July 30, 2020, 6:14 p.m. UTC | #4
On 7/30/2020 1:03 PM, Alex Bennée wrote:
> 
> Steve Sistare <steven.sistare@oracle.com> writes:
> 
>> Provide the -pause command-line parameter and the QEMU_PAUSE environment
>> variable to briefly pause QEMU in main and allow a developer to attach gdb.
>> Useful when the developer does not invoke QEMU directly, such as when using
>> libvirt.
> 
> How does this differ from -S?

The -S flag runs qemu to the main loop but does not start the guest.  Lots of code
that you may need to debug runs before you get there.

- Steve
>> Usage:
>>   qemu -pause <seconds>
>>   or
>>   export QEMU_PAUSE=<seconds>
>>
>> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
>> ---
>>  qemu-options.hx |  9 +++++++++
>>  softmmu/vl.c    | 15 ++++++++++++++-
>>  2 files changed, 23 insertions(+), 1 deletion(-)
>>
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 708583b..8505cf2 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -3668,6 +3668,15 @@ SRST
>>      option is experimental.
>>  ERST
>>  
>> +DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
>> +    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
>> +
>> +SRST
>> +``--pause secs``
>> +    Pause for a number of seconds on entry to main.  Useful for attaching
>> +    a debugger after QEMU has been launched by some other entity.
>> +ERST
>> +
> 
> It seems like having an option to race with the debugger is just asking
> for trouble.
> 
>>  DEF("S", 0, QEMU_OPTION_S, \
>>      "-S              freeze CPU at startup (use 'c' to start execution)\n",
>>      QEMU_ARCH_ALL)
>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>> index 8478778..951994f 100644
>> --- a/softmmu/vl.c
>> +++ b/softmmu/vl.c
>> @@ -2844,7 +2844,7 @@ static void create_default_memdev(MachineState *ms, const char *path)
>>  
>>  void qemu_init(int argc, char **argv, char **envp)
>>  {
>> -    int i;
>> +    int i, seconds;
>>      int snapshot, linux_boot;
>>      const char *initrd_filename;
>>      const char *kernel_filename, *kernel_cmdline;
>> @@ -2882,6 +2882,13 @@ void qemu_init(int argc, char **argv, char **envp)
>>      QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
>>      int mem_prealloc = 0; /* force preallocation of physical target memory */
>>  
>> +    if (getenv("QEMU_PAUSE")) {
>> +        seconds = atoi(getenv("QEMU_PAUSE"));
>> +        printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
>> +               seconds, getpid());
>> +        sleep(seconds);
>> +    }
>> +
>>      os_set_line_buffering();
>>  
>>      error_init(argv[0]);
>> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
>>              case QEMU_OPTION_gdb:
>>                  add_device_config(DEV_GDB, optarg);
>>                  break;
>> +            case QEMU_OPTION_pause:
>> +                seconds = atoi(optarg);
>> +                printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
>> +                            seconds, getpid());
>> +                sleep(seconds);
>> +                break;
>>              case QEMU_OPTION_L:
>>                  if (is_help_option(optarg)) {
>>                      list_data_dirs = true;
> 
>
Alex Bennée July 31, 2020, 9:44 a.m. UTC | #5
Steven Sistare <steven.sistare@oracle.com> writes:

> On 7/30/2020 1:03 PM, Alex Bennée wrote:
>> 
>> Steve Sistare <steven.sistare@oracle.com> writes:
>> 
>>> Provide the -pause command-line parameter and the QEMU_PAUSE environment
>>> variable to briefly pause QEMU in main and allow a developer to attach gdb.
>>> Useful when the developer does not invoke QEMU directly, such as when using
>>> libvirt.
>> 
>> How does this differ from -S?
>
> The -S flag runs qemu to the main loop but does not start the guest.  Lots of code
> that you may need to debug runs before you get there.

Right - so this is for attaching a debugger to QEMU itself, not using
the gdbstub? Why isn't this a problem the calling entity can solve by
the way it invoked QEMU?

We have similar sort of solutions for debugging our testcases:

  https://wiki.qemu.org/Features/QTest#Using_debugging_tools_under_the_test_harness

I still think:

>>> +DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
>>> +    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
>>> +
>>> +SRST
>>> +``--pause secs``
>>> +    Pause for a number of seconds on entry to main.  Useful for attaching
>>> +    a debugger after QEMU has been launched by some other entity.
>>> +ERST
>>> +
>> 
>> It seems like having an option to race with the debugger is just asking
>> for trouble.

this make the option problematic.
Daniel P. Berrangé July 31, 2020, 10:07 a.m. UTC | #6
On Thu, Jul 30, 2020 at 02:11:19PM -0400, Steven Sistare wrote:
> On 7/30/2020 12:20 PM, Eric Blake wrote:
> > On 7/30/20 10:14 AM, Steve Sistare wrote:
> >> Provide the -pause command-line parameter and the QEMU_PAUSE environment
> >> variable to briefly pause QEMU in main and allow a developer to attach gdb.
> >> Useful when the developer does not invoke QEMU directly, such as when using
> >> libvirt.
> > 
> > How would you set this option with libvirt?
> 
> Add -pause in the qemu args in the xml.
>  
> > It feels like you are trying to reinvent something that is already well-documented:
> > 
> > https://www.berrange.com/posts/2011/10/12/debugging-early-startup-of-kvm-with-gdb-when-launched-by-libvirtd/
> 
> Too many steps to reach BINGO for my taste.  Easier is better.  Also, in our shop we start qemu 
> in other ways, such as via services.


A "sleep" is a pretty crude & unreliable way to get into debugging
though. It is racy for a start, but also QEMU has a bunch of stuff
that runs via ELF constructors before main() even starts.

So I feel like the thing that starts QEMU is better placed to provide
a way in for debugging.

eg the service launcher can send SIGSTOP to the child process immediately
before the execve(qemu) call.

Now user can attach with the debugger, allow execution to continue,
and has ability to debug *everything* right from the ELF constructors
onwards into main() and all that follows.

Regards,
Daniel
Steven Sistare July 31, 2020, 3:18 p.m. UTC | #7
On 7/31/2020 6:07 AM, Daniel P. Berrangé wrote:
> On Thu, Jul 30, 2020 at 02:11:19PM -0400, Steven Sistare wrote:
>> On 7/30/2020 12:20 PM, Eric Blake wrote:
>>> On 7/30/20 10:14 AM, Steve Sistare wrote:
>>>> Provide the -pause command-line parameter and the QEMU_PAUSE environment
>>>> variable to briefly pause QEMU in main and allow a developer to attach gdb.
>>>> Useful when the developer does not invoke QEMU directly, such as when using
>>>> libvirt.
>>>
>>> How would you set this option with libvirt?
>>
>> Add -pause in the qemu args in the xml.
>>  
>>> It feels like you are trying to reinvent something that is already well-documented:
>>>
>>> https://www.berrange.com/posts/2011/10/12/debugging-early-startup-of-kvm-with-gdb-when-launched-by-libvirtd/
>>
>> Too many steps to reach BINGO for my taste.  Easier is better.  Also, in our shop we start qemu 
>> in other ways, such as via services.
> 
> A "sleep" is a pretty crude & unreliable way to get into debugging
> though. It is racy for a start, but also QEMU has a bunch of stuff
> that runs via ELF constructors before main() even starts.
> 
> So I feel like the thing that starts QEMU is better placed to provide
> a way in for debugging.
> 
> eg the service launcher can send SIGSTOP to the child process immediately
> before the execve(qemu) call.
> 
> Now user can attach with the debugger, allow execution to continue,
> and has ability to debug *everything* right from the ELF constructors
> onwards into main() and all that follows.
> 
> Regards,
> Daniel

That is a nice solution for the launchers we can modify.
We could use your idea in place of the sleep in main,
    kill(getpid(), SIGSTOP);

Not quite as good as being able to debug the elf constructors, but still helpful.

- Steve
Dr. David Alan Gilbert Sept. 11, 2020, 5:59 p.m. UTC | #8
* Steven Sistare (steven.sistare@oracle.com) wrote:
> On 7/30/2020 1:03 PM, Alex Bennée wrote:
> > 
> > Steve Sistare <steven.sistare@oracle.com> writes:
> > 
> >> Provide the -pause command-line parameter and the QEMU_PAUSE environment
> >> variable to briefly pause QEMU in main and allow a developer to attach gdb.
> >> Useful when the developer does not invoke QEMU directly, such as when using
> >> libvirt.
> > 
> > How does this differ from -S?
> 
> The -S flag runs qemu to the main loop but does not start the guest.  Lots of code
> that you may need to debug runs before you get there.

You might try the '--preconfig' option - that's pretty early on.
The other one is adding a chardev and telling it to wait for a server;
that'll wait until you telnet to the port.

(Either way, this patch shouldn't really be part of this series, it's a
separate discussion)

Dave

> - Steve
> >> Usage:
> >>   qemu -pause <seconds>
> >>   or
> >>   export QEMU_PAUSE=<seconds>
> >>
> >> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
> >> ---
> >>  qemu-options.hx |  9 +++++++++
> >>  softmmu/vl.c    | 15 ++++++++++++++-
> >>  2 files changed, 23 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/qemu-options.hx b/qemu-options.hx
> >> index 708583b..8505cf2 100644
> >> --- a/qemu-options.hx
> >> +++ b/qemu-options.hx
> >> @@ -3668,6 +3668,15 @@ SRST
> >>      option is experimental.
> >>  ERST
> >>  
> >> +DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
> >> +    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
> >> +
> >> +SRST
> >> +``--pause secs``
> >> +    Pause for a number of seconds on entry to main.  Useful for attaching
> >> +    a debugger after QEMU has been launched by some other entity.
> >> +ERST
> >> +
> > 
> > It seems like having an option to race with the debugger is just asking
> > for trouble.
> > 
> >>  DEF("S", 0, QEMU_OPTION_S, \
> >>      "-S              freeze CPU at startup (use 'c' to start execution)\n",
> >>      QEMU_ARCH_ALL)
> >> diff --git a/softmmu/vl.c b/softmmu/vl.c
> >> index 8478778..951994f 100644
> >> --- a/softmmu/vl.c
> >> +++ b/softmmu/vl.c
> >> @@ -2844,7 +2844,7 @@ static void create_default_memdev(MachineState *ms, const char *path)
> >>  
> >>  void qemu_init(int argc, char **argv, char **envp)
> >>  {
> >> -    int i;
> >> +    int i, seconds;
> >>      int snapshot, linux_boot;
> >>      const char *initrd_filename;
> >>      const char *kernel_filename, *kernel_cmdline;
> >> @@ -2882,6 +2882,13 @@ void qemu_init(int argc, char **argv, char **envp)
> >>      QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
> >>      int mem_prealloc = 0; /* force preallocation of physical target memory */
> >>  
> >> +    if (getenv("QEMU_PAUSE")) {
> >> +        seconds = atoi(getenv("QEMU_PAUSE"));
> >> +        printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
> >> +               seconds, getpid());
> >> +        sleep(seconds);
> >> +    }
> >> +
> >>      os_set_line_buffering();
> >>  
> >>      error_init(argv[0]);
> >> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
> >>              case QEMU_OPTION_gdb:
> >>                  add_device_config(DEV_GDB, optarg);
> >>                  break;
> >> +            case QEMU_OPTION_pause:
> >> +                seconds = atoi(optarg);
> >> +                printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
> >> +                            seconds, getpid());
> >> +                sleep(seconds);
> >> +                break;
> >>              case QEMU_OPTION_L:
> >>                  if (is_help_option(optarg)) {
> >>                      list_data_dirs = true;
> > 
> > 
>
Steven Sistare Sept. 24, 2020, 9:51 p.m. UTC | #9
On 9/11/2020 1:59 PM, Dr. David Alan Gilbert wrote:
> * Steven Sistare (steven.sistare@oracle.com) wrote:
>> On 7/30/2020 1:03 PM, Alex Bennée wrote:
>>>
>>> Steve Sistare <steven.sistare@oracle.com> writes:
>>>
>>>> Provide the -pause command-line parameter and the QEMU_PAUSE environment
>>>> variable to briefly pause QEMU in main and allow a developer to attach gdb.
>>>> Useful when the developer does not invoke QEMU directly, such as when using
>>>> libvirt.
>>>
>>> How does this differ from -S?
>>
>> The -S flag runs qemu to the main loop but does not start the guest.  Lots of code
>> that you may need to debug runs before you get there.
> 
> You might try the '--preconfig' option - that's pretty early on.
> The other one is adding a chardev and telling it to wait for a server;
> that'll wait until you telnet to the port.
> 
> (Either way, this patch shouldn't really be part of this series, it's a
> separate discussion)

Sure, I will pull it from the series.

- Steve

>> - Steve
>>>> Usage:
>>>>   qemu -pause <seconds>
>>>>   or
>>>>   export QEMU_PAUSE=<seconds>
>>>>
>>>> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
>>>> ---
>>>>  qemu-options.hx |  9 +++++++++
>>>>  softmmu/vl.c    | 15 ++++++++++++++-
>>>>  2 files changed, 23 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/qemu-options.hx b/qemu-options.hx
>>>> index 708583b..8505cf2 100644
>>>> --- a/qemu-options.hx
>>>> +++ b/qemu-options.hx
>>>> @@ -3668,6 +3668,15 @@ SRST
>>>>      option is experimental.
>>>>  ERST
>>>>  
>>>> +DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
>>>> +    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
>>>> +
>>>> +SRST
>>>> +``--pause secs``
>>>> +    Pause for a number of seconds on entry to main.  Useful for attaching
>>>> +    a debugger after QEMU has been launched by some other entity.
>>>> +ERST
>>>> +
>>>
>>> It seems like having an option to race with the debugger is just asking
>>> for trouble.
>>>
>>>>  DEF("S", 0, QEMU_OPTION_S, \
>>>>      "-S              freeze CPU at startup (use 'c' to start execution)\n",
>>>>      QEMU_ARCH_ALL)
>>>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>>>> index 8478778..951994f 100644
>>>> --- a/softmmu/vl.c
>>>> +++ b/softmmu/vl.c
>>>> @@ -2844,7 +2844,7 @@ static void create_default_memdev(MachineState *ms, const char *path)
>>>>  
>>>>  void qemu_init(int argc, char **argv, char **envp)
>>>>  {
>>>> -    int i;
>>>> +    int i, seconds;
>>>>      int snapshot, linux_boot;
>>>>      const char *initrd_filename;
>>>>      const char *kernel_filename, *kernel_cmdline;
>>>> @@ -2882,6 +2882,13 @@ void qemu_init(int argc, char **argv, char **envp)
>>>>      QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
>>>>      int mem_prealloc = 0; /* force preallocation of physical target memory */
>>>>  
>>>> +    if (getenv("QEMU_PAUSE")) {
>>>> +        seconds = atoi(getenv("QEMU_PAUSE"));
>>>> +        printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
>>>> +               seconds, getpid());
>>>> +        sleep(seconds);
>>>> +    }
>>>> +
>>>>      os_set_line_buffering();
>>>>  
>>>>      error_init(argv[0]);
>>>> @@ -3204,6 +3211,12 @@ void qemu_init(int argc, char **argv, char **envp)
>>>>              case QEMU_OPTION_gdb:
>>>>                  add_device_config(DEV_GDB, optarg);
>>>>                  break;
>>>> +            case QEMU_OPTION_pause:
>>>> +                seconds = atoi(optarg);
>>>> +                printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
>>>> +                            seconds, getpid());
>>>> +                sleep(seconds);
>>>> +                break;
>>>>              case QEMU_OPTION_L:
>>>>                  if (is_help_option(optarg)) {
>>>>                      list_data_dirs = true;
>>>
>>>
>>
diff mbox series

Patch

diff --git a/qemu-options.hx b/qemu-options.hx
index 708583b..8505cf2 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3668,6 +3668,15 @@  SRST
     option is experimental.
 ERST
 
+DEF("pause", HAS_ARG, QEMU_OPTION_pause, \
+    "-pause secs    Pause for secs seconds on entry to main.\n", QEMU_ARCH_ALL)
+
+SRST
+``--pause secs``
+    Pause for a number of seconds on entry to main.  Useful for attaching
+    a debugger after QEMU has been launched by some other entity.
+ERST
+
 DEF("S", 0, QEMU_OPTION_S, \
     "-S              freeze CPU at startup (use 'c' to start execution)\n",
     QEMU_ARCH_ALL)
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 8478778..951994f 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2844,7 +2844,7 @@  static void create_default_memdev(MachineState *ms, const char *path)
 
 void qemu_init(int argc, char **argv, char **envp)
 {
-    int i;
+    int i, seconds;
     int snapshot, linux_boot;
     const char *initrd_filename;
     const char *kernel_filename, *kernel_cmdline;
@@ -2882,6 +2882,13 @@  void qemu_init(int argc, char **argv, char **envp)
     QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
     int mem_prealloc = 0; /* force preallocation of physical target memory */
 
+    if (getenv("QEMU_PAUSE")) {
+        seconds = atoi(getenv("QEMU_PAUSE"));
+        printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
+               seconds, getpid());
+        sleep(seconds);
+    }
+
     os_set_line_buffering();
 
     error_init(argv[0]);
@@ -3204,6 +3211,12 @@  void qemu_init(int argc, char **argv, char **envp)
             case QEMU_OPTION_gdb:
                 add_device_config(DEV_GDB, optarg);
                 break;
+            case QEMU_OPTION_pause:
+                seconds = atoi(optarg);
+                printf("Pausing %d seconds for debugger. QEMU PID is %d\n",
+                            seconds, getpid());
+                sleep(seconds);
+                break;
             case QEMU_OPTION_L:
                 if (is_help_option(optarg)) {
                     list_data_dirs = true;