diff mbox

[v2] qemu-char: fix terminal crash when using "-monitor stdio -nographic"

Message ID 1410261588-8360-1-git-send-email-john.liuli@huawei.com
State New
Headers show

Commit Message

john.liuli Sept. 9, 2014, 11:19 a.m. UTC
From: Li Liu <john.liuli@huawei.com>

Eeay to reproduce, just try "qemu -monitor stdio -nographic"
and type "quit", then the terminal will be crashed.

There are two pathes try to call tcgetattr of stdio in vl.c:

1) Monitor_parse(optarg, "readline");
   .....
   qemu_opts_foreach(qemu_find_opts("chardev"),
                     chardev_init_func, NULL, 1) != 0)

2) if (default_serial)
   add_device_config(DEV_SERIAL, "stdio");
   ....
   if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)

Both of them will trigger qemu_chr_open_stdio which will disable
ECHO attributes. First one has updated the attributes of stdio
by calling qemu_chr_fe_set_echo(chr, false). And the tty
attributes has been saved in oldtty. Then the second path will
redo such actions, and the oldtty is overlapped. So till "quit",
term_exit can't recove the correct attributes.

Signed-off-by: Li Liu <john.liuli@huawei.com>
---
changes v1 -> v2:
1) as Markus Armbruster and Gerd Hoffmann suggested :
   Multiple character devices can't use the same terminal.
   So catch and reject the attempt if stdio is opened already.

---
 qemu-char.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

Comments

Michael Tokarev Sept. 15, 2014, 12:50 p.m. UTC | #1
09.09.2014 15:19, john.liuli wrote:
> From: Li Liu <john.liuli@huawei.com>
> 
> Eeay to reproduce, just try "qemu -monitor stdio -nographic"
> and type "quit", then the terminal will be crashed.
> 
> There are two pathes try to call tcgetattr of stdio in vl.c:

This looks reasonable.  Except of one thing -- how about renaming
stdio_is_ready to stdio_in_use?  (I can do that when applying, no
need to resend anythnig).  Because, well, stdio_is_ready is not
obvious at all, at least to me... :)

Thank you for fixing this!

/mjt
Michael Tokarev Sept. 15, 2014, 12:57 p.m. UTC | #2
15.09.2014 16:50, Michael Tokarev пишет:
> 09.09.2014 15:19, john.liuli wrote:
>> From: Li Liu <john.liuli@huawei.com>
>>
>> Eeay to reproduce, just try "qemu -monitor stdio -nographic"
>> and type "quit", then the terminal will be crashed.
>>
>> There are two pathes try to call tcgetattr of stdio in vl.c:
> 
> This looks reasonable.  Except of one thing -- how about renaming
> stdio_is_ready to stdio_in_use?  (I can do that when applying, no
> need to resend anythnig).  Because, well, stdio_is_ready is not
> obvious at all, at least to me... :)

And oh, the commit comment -- it is not 'terminal crash', it is
'terminal misbehavor' or something like that.  Terminal does not
crash, it just does not have proper settings after qemu exits.

/mjt
Gerd Hoffmann Sept. 15, 2014, 1:29 p.m. UTC | #3
On Mo, 2014-09-15 at 16:57 +0400, Michael Tokarev wrote:
> 15.09.2014 16:50, Michael Tokarev пишет:
> > 09.09.2014 15:19, john.liuli wrote:
> >> From: Li Liu <john.liuli@huawei.com>
> >>
> >> Eeay to reproduce, just try "qemu -monitor stdio -nographic"
> >> and type "quit", then the terminal will be crashed.
> >>
> >> There are two pathes try to call tcgetattr of stdio in vl.c:
> > 
> > This looks reasonable.  Except of one thing -- how about renaming
> > stdio_is_ready to stdio_in_use?  (I can do that when applying, no
> > need to resend anythnig).  Because, well, stdio_is_ready is not
> > obvious at all, at least to me... :)
> 
> And oh, the commit comment -- it is not 'terminal crash', it is
> 'terminal misbehavor' or something like that.  Terminal does not
> crash, it just does not have proper settings after qemu exits.

For the record:  The 'reset' utility does a full terminal reset and
restores sane settings.  So usually you can recover from any terminal
f*ckup like this by first hitting Ctrl-C [1], then type "reset" [2],
then hit Enter.

HTH,
  Gerd

[1] To cancel anything which might be at your shell prompt.
[2] Possibly blindly in case echo happens to be turned off.
Markus Armbruster Sept. 15, 2014, 1:33 p.m. UTC | #4
Michael Tokarev <mjt@tls.msk.ru> writes:

> 15.09.2014 16:50, Michael Tokarev пишет:
>> 09.09.2014 15:19, john.liuli wrote:
>>> From: Li Liu <john.liuli@huawei.com>
>>>
>>> Eeay to reproduce, just try "qemu -monitor stdio -nographic"
>>> and type "quit", then the terminal will be crashed.
>>>
>>> There are two pathes try to call tcgetattr of stdio in vl.c:
>> 
>> This looks reasonable.  Except of one thing -- how about renaming
>> stdio_is_ready to stdio_in_use?  (I can do that when applying, no
>> need to resend anythnig).  Because, well, stdio_is_ready is not
>> obvious at all, at least to me... :)
>
> And oh, the commit comment -- it is not 'terminal crash', it is
> 'terminal misbehavor' or something like that.  Terminal does not
> crash, it just does not have proper settings after qemu exits.

Maybe

    qemu-char: Permit only a single "stdio" character device

    When more than one is used, the terminal settings aren't restored
    correctly on exit.  Fixable.  However, such usage makes no sense,
    because the users race for input, so outlaw it instead.

    If you want to connect multiple things to stdio, use the mux
    chardev.

With the rename proposed by Michael:

Reviewed-by: Markus Armbruster <armbru@redhat.com>
john.liuli Sept. 16, 2014, 1:40 a.m. UTC | #5
On 2014/9/15 20:57, Michael Tokarev wrote:
> 15.09.2014 16:50, Michael Tokarev пишет:
>> 09.09.2014 15:19, john.liuli wrote:
>>> From: Li Liu <john.liuli@huawei.com>
>>>
>>> Eeay to reproduce, just try "qemu -monitor stdio -nographic"
>>> and type "quit", then the terminal will be crashed.
>>>
>>> There are two pathes try to call tcgetattr of stdio in vl.c:
>>
>> This looks reasonable.  Except of one thing -- how about renaming
>> stdio_is_ready to stdio_in_use?  (I can do that when applying, no
>> need to resend anythnig).  Because, well, stdio_is_ready is not
>> obvious at all, at least to me... :)
> 
> And oh, the commit comment -- it is not 'terminal crash', it is
> 'terminal misbehavor' or something like that.  Terminal does not
> crash, it just does not have proper settings after qemu exits.
> 
> /mjt
> 

Thanks four your comments! Can you help do this when applying
incidentally? Or I will resend it again?

Best Regards,

Li.

> .
>
Michael Tokarev Sept. 16, 2014, 4:20 a.m. UTC | #6
16.09.2014 05:40, Li Liu wrote:
> Thanks four your comments! Can you help do this when applying
> incidentally? Or I will resend it again?

http://git.corpit.ru/?p=qemu.git;a=commit;h=6dbc7173f25747b2ed9f3f322ac9697feffe4bf7 --
applied yesteday :)

Thanks,

/mjt
diff mbox

Patch

diff --git a/qemu-char.c b/qemu-char.c
index d4f327a..f8f0c48 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1017,6 +1017,7 @@  static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
+static bool stdio_is_ready;
 static bool stdio_allow_signal;
 
 static void term_exit(void)
@@ -1060,8 +1061,15 @@  static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
         error_report("cannot use stdio with -daemonize");
         return NULL;
     }
+
+    if (stdio_is_ready) {
+        error_report("cannot use stdio by multiple character devices");
+        exit(1);
+    }
+
+    stdio_is_ready = true;
     old_fd0_flags = fcntl(0, F_GETFL);
-    tcgetattr (0, &oldtty);
+    tcgetattr(0, &oldtty);
     qemu_set_nonblock(0);
     atexit(term_exit);