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

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



chardev patches

# gpg: Signature made Wed 03 Oct 2018 11:57:34 BST
# gpg:                using RSA key DAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>"
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>"
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* remotes/elmarco/tags/chardev-pull-request:
  chardev: use a child source for qio input source
  chardev: mark the calls that allow an implicit mux monitor
  char.h: fix gtk-doc comment style
  chardev: unref if underlying chardev has no parent
  chardev: remove qemu_chr_fe_read_all() counter
  chardev: avoid crash if no associated address

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents dafd9505 a7077b8e
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len)
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
{
    Chardev *s = be->chr;
    int offset = 0, counter = 10;
    int offset = 0;
    int res;

    if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) {
@@ -88,10 +88,6 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
        }

        offset += res;

        if (!counter--) {
            break;
        }
    }

    if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) {
@@ -239,7 +235,12 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
            d->backends[b->tag] = NULL;
        }
        if (del) {
            object_unparent(OBJECT(b->chr));
            Object *obj = OBJECT(b->chr);
            if (obj->parent) {
                object_unparent(obj);
            } else {
                object_unref(obj);
            }
        }
        b->chr = NULL;
    }
+5 −43
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ typedef struct IOWatchPoll {
    IOCanReadHandler *fd_can_read;
    GSourceFunc fd_read;
    void *opaque;
    GMainContext *context;
} IOWatchPoll;

static IOWatchPoll *io_watch_poll_from_source(GSource *source)
@@ -55,47 +54,24 @@ static gboolean io_watch_poll_prepare(GSource *source,
        iwp->src = qio_channel_create_watch(
            iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
        g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
        g_source_attach(iwp->src, iwp->context);
    } else {
        g_source_destroy(iwp->src);
        g_source_add_child_source(source, iwp->src);
        g_source_unref(iwp->src);
    } else {
        g_source_remove_child_source(source, iwp->src);
        iwp->src = NULL;
    }
    return FALSE;
}

static gboolean io_watch_poll_check(GSource *source)
{
    return FALSE;
}

static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
                                       gpointer user_data)
{
    abort();
}

static void io_watch_poll_finalize(GSource *source)
{
    /* Due to a glib bug, removing the last reference to a source
     * inside a finalize callback causes recursive locking (and a
     * deadlock).  This is not a problem inside other callbacks,
     * including dispatch callbacks, so we call io_remove_watch_poll
     * to remove this source.  At this point, iwp->src must
     * be NULL, or we would leak it.
     *
     * This would be solved much more elegantly by child sources,
     * but we support older glib versions that do not have them.
     */
    IOWatchPoll *iwp = io_watch_poll_from_source(source);
    assert(iwp->src == NULL);
    return G_SOURCE_CONTINUE;
}

static GSourceFuncs io_watch_poll_funcs = {
    .prepare = io_watch_poll_prepare,
    .check = io_watch_poll_check,
    .dispatch = io_watch_poll_dispatch,
    .finalize = io_watch_poll_finalize,
};

GSource *io_add_watch_poll(Chardev *chr,
@@ -115,7 +91,6 @@ GSource *io_add_watch_poll(Chardev *chr,
    iwp->ioc = ioc;
    iwp->fd_read = (GSourceFunc) fd_read;
    iwp->src = NULL;
    iwp->context = context;

    name = g_strdup_printf("chardev-iowatch-%s", chr->label);
    g_source_set_name((GSource *)iwp, name);
@@ -126,23 +101,10 @@ GSource *io_add_watch_poll(Chardev *chr,
    return (GSource *)iwp;
}

static void io_remove_watch_poll(GSource *source)
{
    IOWatchPoll *iwp;

    iwp = io_watch_poll_from_source(source);
    if (iwp->src) {
        g_source_destroy(iwp->src);
        g_source_unref(iwp->src);
        iwp->src = NULL;
    }
    g_source_destroy(&iwp->parent);
}

void remove_fd_in_watch(Chardev *chr)
{
    if (chr->gsource) {
        io_remove_watch_poll(chr->gsource);
        g_source_destroy(chr->gsource);
        chr->gsource = NULL;
    }
}
+6 −2
Original line number Diff line number Diff line
@@ -423,8 +423,12 @@ static void update_disconnected_filename(SocketChardev *s)
    Chardev *chr = CHARDEV(s);

    g_free(chr->filename);
    if (s->addr) {
        chr->filename = SocketAddress_to_str("disconnected:", s->addr,
                                             s->is_listen, s->is_telnet);
    } else {
        chr->filename = g_strdup("disconnected:socket");
    }
}

/* NB may be called even if tcp_chr_connect has not been
+30 −7
Original line number Diff line number Diff line
@@ -329,7 +329,8 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp)
    return 0;
}

QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename,
                                bool permit_mux_mon)
{
    char host[65], port[33], width[8], height[8];
    int pos;
@@ -344,6 +345,10 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
    }

    if (strstart(filename, "mon:", &p)) {
        if (!permit_mux_mon) {
            error_report("mon: isn't supported in this context");
            return NULL;
        }
        filename = p;
        qemu_opt_set(opts, "mux", "on", &error_abort);
        if (strcmp(filename, "stdio") == 0) {
@@ -683,7 +688,8 @@ out:
    return chr;
}

Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
                               bool permit_mux_mon)
{
    const char *p;
    Chardev *chr;
@@ -694,25 +700,32 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
        return qemu_chr_find(p);
    }

    opts = qemu_chr_parse_compat(label, filename);
    opts = qemu_chr_parse_compat(label, filename, permit_mux_mon);
    if (!opts)
        return NULL;

    chr = qemu_chr_new_from_opts(opts, &err);
    if (err) {
    if (!chr) {
        error_report_err(err);
        goto out;
    }
    if (chr && qemu_opt_get_bool(opts, "mux", 0)) {

    if (qemu_opt_get_bool(opts, "mux", 0)) {
        assert(permit_mux_mon);
        monitor_init(chr, MONITOR_USE_READLINE);
    }

out:
    qemu_opts_del(opts);
    return chr;
}

Chardev *qemu_chr_new(const char *label, const char *filename)
static Chardev *qemu_chr_new_permit_mux_mon(const char *label,
                                          const char *filename,
                                          bool permit_mux_mon)
{
    Chardev *chr;
    chr = qemu_chr_new_noreplay(label, filename);
    chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon);
    if (chr) {
        if (replay_mode != REPLAY_MODE_NONE) {
            qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
@@ -726,6 +739,16 @@ Chardev *qemu_chr_new(const char *label, const char *filename)
    return chr;
}

Chardev *qemu_chr_new(const char *label, const char *filename)
{
    return qemu_chr_new_permit_mux_mon(label, filename, false);
}

Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename)
{
    return qemu_chr_new_permit_mux_mon(label, filename, true);
}

static int qmp_query_chardev_foreach(Object *obj, void *data)
{
    Chardev *chr = CHARDEV(obj);
+5 −1
Original line number Diff line number Diff line
@@ -2038,7 +2038,11 @@ int gdbserver_start(const char *device)
            sigaction(SIGINT, &act, NULL);
        }
#endif
        chr = qemu_chr_new_noreplay("gdb", device);
        /*
         * FIXME: it's a bit weird to allow using a mux chardev here
         * and implicitly setup a monitor. We may want to break this.
         */
        chr = qemu_chr_new_noreplay("gdb", device, true);
        if (!chr)
            return -1;
    }
Loading