Commit a80bf99fa3dd829ecea88b9bfb4f7cf146208f07

Authored by aliguori
1 parent 2970a6c9

char-mux: Use separate input buffers (Jan Kiszka)

Currently, the intermediate input buffer of mux'ed character devices
records data across all sub-devices. This has the side effect that we
easily leak data recorded over one sub-devices to another once we switch
the focus. Avoid data loss and confusion by defining exclusive buffers.

Note: In contrast to the original author's claim, the buffering concept
still breaks down when the fifo of the currently active sub-device is
full. As we cannot accept futher data from this point on without risking
to loose it, we will also miss escape sequences, just like without all
that buffering. In short: There is no reliable escape sequence handling
without infinite buffers or the risk of loosing some data.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6701 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 14 additions and 10 deletions
qemu-char.c
@@ -225,12 +225,15 @@ typedef struct { @@ -225,12 +225,15 @@ typedef struct {
225 IOEventHandler *chr_event[MAX_MUX]; 225 IOEventHandler *chr_event[MAX_MUX];
226 void *ext_opaque[MAX_MUX]; 226 void *ext_opaque[MAX_MUX];
227 CharDriverState *drv; 227 CharDriverState *drv;
228 - unsigned char buffer[MUX_BUFFER_SIZE];  
229 - int prod;  
230 - int cons;  
231 int mux_cnt; 228 int mux_cnt;
232 int term_got_escape; 229 int term_got_escape;
233 int max_size; 230 int max_size;
  231 + /* Intermediate input buffer allows to catch escape sequences even if the
  232 + currently active device is not accepting any input - but only until it
  233 + is full as well. */
  234 + unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
  235 + int prod[MAX_MUX];
  236 + int cons[MAX_MUX];
234 } MuxDriver; 237 } MuxDriver;
235 238
236 239
@@ -360,11 +363,11 @@ static void mux_chr_accept_input(CharDriverState *chr) @@ -360,11 +363,11 @@ static void mux_chr_accept_input(CharDriverState *chr)
360 int m = chr->focus; 363 int m = chr->focus;
361 MuxDriver *d = chr->opaque; 364 MuxDriver *d = chr->opaque;
362 365
363 - while (d->prod != d->cons && 366 + while (d->prod[m] != d->cons[m] &&
364 d->chr_can_read[m] && 367 d->chr_can_read[m] &&
365 d->chr_can_read[m](d->ext_opaque[m])) { 368 d->chr_can_read[m](d->ext_opaque[m])) {
366 d->chr_read[m](d->ext_opaque[m], 369 d->chr_read[m](d->ext_opaque[m],
367 - &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); 370 + &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
368 } 371 }
369 } 372 }
370 373
@@ -372,11 +375,12 @@ static int mux_chr_can_read(void *opaque) @@ -372,11 +375,12 @@ static int mux_chr_can_read(void *opaque)
372 { 375 {
373 CharDriverState *chr = opaque; 376 CharDriverState *chr = opaque;
374 MuxDriver *d = chr->opaque; 377 MuxDriver *d = chr->opaque;
  378 + int m = chr->focus;
375 379
376 - if ((d->prod - d->cons) < MUX_BUFFER_SIZE) 380 + if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE)
377 return 1; 381 return 1;
378 - if (d->chr_can_read[chr->focus])  
379 - return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); 382 + if (d->chr_can_read[m])
  383 + return d->chr_can_read[m](d->ext_opaque[m]);
380 return 0; 384 return 0;
381 } 385 }
382 386
@@ -391,12 +395,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) @@ -391,12 +395,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
391 395
392 for(i = 0; i < size; i++) 396 for(i = 0; i < size; i++)
393 if (mux_proc_byte(chr, d, buf[i])) { 397 if (mux_proc_byte(chr, d, buf[i])) {
394 - if (d->prod == d->cons && 398 + if (d->prod[m] == d->cons[m] &&
395 d->chr_can_read[m] && 399 d->chr_can_read[m] &&
396 d->chr_can_read[m](d->ext_opaque[m])) 400 d->chr_can_read[m](d->ext_opaque[m]))
397 d->chr_read[m](d->ext_opaque[m], &buf[i], 1); 401 d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
398 else 402 else
399 - d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; 403 + d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
400 } 404 }
401 } 405 }
402 406