Commit c4c5f657 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/elmarco/tags/chardev-pull-request' into staging



Chardev fixes

# gpg: Signature made Wed 13 Feb 2019 16:18:36 GMT
# gpg:                using RSA key DAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* remotes/elmarco/tags/chardev-pull-request: (25 commits)
  char-pty: remove write_lock usage
  char-pty: remove the check for connection on write
  chardev: add a note about frontend sources and context switch
  terminal3270: do not use backend timer sources
  char: update the mux handlers in class callback
  chardev/wctablet: Fix a typo
  char: allow specifying a GMainContext at opening time
  chardev: ensure termios is fully initialized
  tests: expand coverage of socket chardev test
  chardev: fix race with client connections in tcp_chr_wait_connected
  chardev: disallow TLS/telnet/websocket with tcp_chr_wait_connected
  chardev: honour the reconnect setting in tcp_chr_wait_connected
  chardev: use a state machine for socket connection state
  chardev: split up qmp_chardev_open_socket connection code
  chardev: split tcp_chr_wait_connected into two methods
  chardev: remove unused 'sioc' variable & cleanup paths
  chardev: ensure qemu_chr_parse_compat reports missing driver error
  chardev: remove many local variables in qemu_chr_parse_socket
  chardev: forbid 'wait' option with client sockets
  chardev: forbid 'reconnect' option with server sockets
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 4856c2c7 f7ea2038
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -246,14 +246,15 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
    }
}

void qemu_chr_fe_set_handlers(CharBackend *b,
void qemu_chr_fe_set_handlers_full(CharBackend *b,
                                   IOCanReadHandler *fd_can_read,
                                   IOReadHandler *fd_read,
                                   IOEventHandler *fd_event,
                                   BackendChangeHandler *be_change,
                                   void *opaque,
                                   GMainContext *context,
                              bool set_open)
                                   bool set_open,
                                   bool sync_state)
{
    Chardev *s;
    int fe_open;
@@ -285,14 +286,24 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
        qemu_chr_fe_take_focus(b);
        /* We're connecting to an already opened device, so let's make sure we
           also get the open event */
        if (s->be_open) {
        if (sync_state && s->be_open) {
            qemu_chr_be_event(s, CHR_EVENT_OPENED);
        }
    }

    if (CHARDEV_IS_MUX(s)) {
        mux_chr_set_handlers(s, context);
}

void qemu_chr_fe_set_handlers(CharBackend *b,
                              IOCanReadHandler *fd_can_read,
                              IOReadHandler *fd_read,
                              IOEventHandler *fd_event,
                              BackendChangeHandler *be_change,
                              void *opaque,
                              GMainContext *context,
                              bool set_open)
{
    qemu_chr_fe_set_handlers_full(b, fd_can_read, fd_read, fd_event, be_change,
                                  opaque, context, set_open,
                                  true);
}

void qemu_chr_fe_take_focus(CharBackend *b)
+10 −9
Original line number Diff line number Diff line
@@ -278,18 +278,18 @@ static void char_mux_finalize(Object *obj)
    qemu_chr_fe_deinit(&d->chr, false);
}

void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
static void mux_chr_update_read_handlers(Chardev *chr)
{
    MuxChardev *d = MUX_CHARDEV(chr);

    /* Fix up the real driver with mux routines */
    qemu_chr_fe_set_handlers(&d->chr,
    qemu_chr_fe_set_handlers_full(&d->chr,
                                  mux_chr_can_read,
                                  mux_chr_read,
                                  mux_chr_event,
                                  NULL,
                                  chr,
                             context, true);
                                  chr->gcontext, true, false);
}

void mux_set_focus(Chardev *chr, int focus)
@@ -367,7 +367,7 @@ static int open_muxes(Chardev *chr)
     * mark mux as OPENED so any new FEs will immediately receive
     * OPENED event
     */
    qemu_chr_be_event(chr, CHR_EVENT_OPENED);
    chr->be_open = 1;

    return 0;
}
@@ -383,6 +383,7 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
    cc->chr_add_watch = mux_chr_add_watch;
    cc->chr_be_event = mux_chr_be_event;
    cc->chr_machine_done = open_muxes;
    cc->chr_update_read_handler = mux_chr_update_read_handlers;
}

static const TypeInfo char_mux_type_info = {
+4 −52
Original line number Diff line number Diff line
@@ -36,15 +36,12 @@ typedef struct {
    QIOChannel *ioc;
    int read_bytes;

    /* Protected by the Chardev chr_write_lock.  */
    int connected;
    GSource *timer_src;
    GSource *open_source;
} PtyChardev;

#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)

static void pty_chr_update_read_handler_locked(Chardev *chr);
static void pty_chr_state(Chardev *chr, int connected);

static void pty_chr_timer_cancel(PtyChardev *s)
@@ -56,32 +53,19 @@ static void pty_chr_timer_cancel(PtyChardev *s)
    }
}

static void pty_chr_open_src_cancel(PtyChardev *s)
{
    if (s->open_source) {
        g_source_destroy(s->open_source);
        g_source_unref(s->open_source);
        s->open_source = NULL;
    }
}

static gboolean pty_chr_timer(gpointer opaque)
{
    struct Chardev *chr = CHARDEV(opaque);
    PtyChardev *s = PTY_CHARDEV(opaque);

    qemu_mutex_lock(&chr->chr_write_lock);
    pty_chr_timer_cancel(s);
    pty_chr_open_src_cancel(s);
    if (!s->connected) {
        /* Next poll ... */
        pty_chr_update_read_handler_locked(chr);
        qemu_chr_be_update_read_handlers(chr, chr->gcontext);
    }
    qemu_mutex_unlock(&chr->chr_write_lock);
    return FALSE;
}

/* Called with chr_write_lock held.  */
static void pty_chr_rearm_timer(Chardev *chr, int ms)
{
    PtyChardev *s = PTY_CHARDEV(chr);
@@ -94,8 +78,7 @@ static void pty_chr_rearm_timer(Chardev *chr, int ms)
    g_free(name);
}

/* Called with chr_write_lock held.  */
static void pty_chr_update_read_handler_locked(Chardev *chr)
static void pty_chr_update_read_handler(Chardev *chr)
{
    PtyChardev *s = PTY_CHARDEV(chr);
    GPollFD pfd;
@@ -117,25 +100,13 @@ static void pty_chr_update_read_handler_locked(Chardev *chr)
    }
}

static void pty_chr_update_read_handler(Chardev *chr)
{
    qemu_mutex_lock(&chr->chr_write_lock);
    pty_chr_update_read_handler_locked(chr);
    qemu_mutex_unlock(&chr->chr_write_lock);
}

/* Called with chr_write_lock held.  */
static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
    PtyChardev *s = PTY_CHARDEV(chr);

    if (!s->connected) {
        /* guest sends data, check for (re-)connect */
        pty_chr_update_read_handler_locked(chr);
    if (!s->connected) {
        return len;
    }
    }
    return io_channel_send(s->ioc, buf, len);
}

@@ -183,23 +154,11 @@ static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
    return TRUE;
}

static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
{
    Chardev *chr = CHARDEV(opaque);
    PtyChardev *s = PTY_CHARDEV(opaque);

    s->open_source = NULL;
    qemu_chr_be_event(chr, CHR_EVENT_OPENED);
    return FALSE;
}

/* Called with chr_write_lock held.  */
static void pty_chr_state(Chardev *chr, int connected)
{
    PtyChardev *s = PTY_CHARDEV(chr);

    if (!connected) {
        pty_chr_open_src_cancel(s);
        remove_fd_in_watch(chr);
        s->connected = 0;
        /* (re-)connect poll interval for idle guests: once per second.
@@ -209,13 +168,8 @@ static void pty_chr_state(Chardev *chr, int connected)
    } else {
        pty_chr_timer_cancel(s);
        if (!s->connected) {
            g_assert(s->open_source == NULL);
            s->open_source = g_idle_source_new();
            s->connected = 1;
            g_source_set_callback(s->open_source,
                                  qemu_chr_be_generic_open_func,
                                  chr, NULL);
            g_source_attach(s->open_source, chr->gcontext);
            qemu_chr_be_event(chr, CHR_EVENT_OPENED);
        }
        if (!chr->gsource) {
            chr->gsource = io_add_watch_poll(chr, s->ioc,
@@ -231,11 +185,9 @@ static void char_pty_finalize(Object *obj)
    Chardev *chr = CHARDEV(obj);
    PtyChardev *s = PTY_CHARDEV(obj);

    qemu_mutex_lock(&chr->chr_write_lock);
    pty_chr_state(chr, 0);
    object_unref(OBJECT(s->ioc));
    pty_chr_timer_cancel(s);
    qemu_mutex_unlock(&chr->chr_write_lock);
    qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}

+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ static void qmp_chardev_open_serial(Chardev *chr,
static void tty_serial_init(int fd, int speed,
                            int parity, int data_bits, int stop_bits)
{
    struct termios tty;
    struct termios tty = {0};
    speed_t spd;

#if 0
+355 −135

File changed.

Preview size limit exceeded, changes collapsed.

Loading