[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 4/8] chardev: fix fd_chr_add_watch() when in != out
From: |
marcandre . lureau |
Subject: |
[PULL 4/8] chardev: fix fd_chr_add_watch() when in != out |
Date: |
Thu, 5 Aug 2021 16:53:27 +0400 |
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Create child sources for the different streams, and dispatch on the
parent source with the synthesized conditions.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
chardev/char-fd.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index 1cd62f2779..743d3989b4 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -28,6 +28,7 @@
#include "qemu/sockets.h"
#include "qapi/error.h"
#include "chardev/char.h"
+#include "chardev/char-fe.h"
#include "io/channel-file.h"
#include "chardev/char-fd.h"
@@ -80,10 +81,85 @@ static int fd_chr_read_poll(void *opaque)
return s->max_size;
}
+typedef struct FDSource {
+ GSource parent;
+
+ GIOCondition cond;
+} FDSource;
+
+static gboolean
+fd_source_prepare(GSource *source,
+ gint *timeout_)
+{
+ FDSource *src = (FDSource *)source;
+
+ return src->cond != 0;
+}
+
+static gboolean
+fd_source_check(GSource *source)
+{
+ FDSource *src = (FDSource *)source;
+
+ return src->cond != 0;
+}
+
+static gboolean
+fd_source_dispatch(GSource *source, GSourceFunc callback,
+ gpointer user_data)
+{
+ FDSource *src = (FDSource *)source;
+ FEWatchFunc func = (FEWatchFunc)callback;
+ gboolean ret = G_SOURCE_CONTINUE;
+
+ if (src->cond) {
+ ret = func(NULL, src->cond, user_data);
+ src->cond = 0;
+ }
+
+ return ret;
+}
+
+static GSourceFuncs fd_source_funcs = {
+ fd_source_prepare,
+ fd_source_check,
+ fd_source_dispatch,
+ NULL, NULL, NULL
+};
+
+static GSource *fd_source_new(FDChardev *chr)
+{
+ return g_source_new(&fd_source_funcs, sizeof(FDSource));
+}
+
+static gboolean child_func(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ FDSource *parent = data;
+
+ parent->cond |= condition;
+
+ return G_SOURCE_CONTINUE;
+}
+
static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
{
FDChardev *s = FD_CHARDEV(chr);
- return qio_channel_create_watch(s->ioc_out, cond);
+ g_autoptr(GSource) source = fd_source_new(s);
+
+ if (s->ioc_out) {
+ g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_out, cond &
~G_IO_IN);
+ g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
+ g_source_add_child_source(source, child);
+ }
+ if (s->ioc_in) {
+ g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_in, cond &
~G_IO_OUT);
+ g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
+ g_source_add_child_source(source, child);
+ }
+
+ return g_steal_pointer(&source);
}
static void fd_chr_update_read_handler(Chardev *chr)
--
2.32.0.264.g75ae10bc75
- [PULL 0/8] chardev fixes for 6.1, marcandre . lureau, 2021/08/05
- [PULL 1/8] util: fix abstract socket path copy, marcandre . lureau, 2021/08/05
- [PULL 2/8] chardev/socket: print a more correct command-line address, marcandre . lureau, 2021/08/05
- [PULL 3/8] chardev: mark explicitly first argument as poisoned, marcandre . lureau, 2021/08/05
- [PULL 4/8] chardev: fix fd_chr_add_watch() when in != out,
marcandre . lureau <=
- [PULL 5/8] chardev: fix qemu_chr_open_fd() being called with fd=-1, marcandre . lureau, 2021/08/05
- [PULL 6/8] chardev: fix qemu_chr_open_fd() with fd_in==fd_out, marcandre . lureau, 2021/08/05
- [PULL 7/8] chardev: give some context on chardev-add error, marcandre . lureau, 2021/08/05
- [PULL 8/8] chardev: report a simpler error about duplicated id, marcandre . lureau, 2021/08/05
- Re: [PULL 0/8] chardev fixes for 6.1, Peter Maydell, 2021/08/05