* [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests
@ 2017-02-02 14:51 Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 01/22] char: remove qemu_chr_be_generic_open Marc-André Lureau
` (21 more replies)
0 siblings, 22 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Hi,
The following series contains various patches:
- chardev and other clean-ups
- replace "chardevs" list for a /chardevs container object
- add a few read-only socket properties mainly useful for testing
- add various chardev tests
This series is part of a larger refactoring series that I try to keep
up to date here: https://github.com/elmarco/qemu/commits/chrfe
Marc-André Lureau (22):
char: remove qemu_chr_be_generic_open
mux: simplfy muxes_realize_done
xen: use a better chardev type check
container: don't leak container reference
main: free root container
char: add a /chardevs container
char: use /chardevs container instead of chardevs list
char: remove qemu_chardev_add
char: remove chardevs list
char: useless NULL check
qcow2: remove useless NULL check
char-socket: introduce update_disconnected_filename()
char-socket: update local address after listen
char-socket: add 'addr' property
char-socket: add 'connected' property
char-udp: flush as much buffer as possible
tests: add alias check in /char/ringbuf
tests: add /char/pipe test
tests: add /char/file test
tests: add /char/socket test
tests: add /char/udp test
tests: add /char/console test
chardev/char-mux.h | 2 +-
include/sysemu/char.h | 12 +-
block/qcow2.c | 4 +-
chardev/char-mux.c | 11 +-
chardev/char-pty.c | 2 +-
chardev/char-socket.c | 46 ++++++-
chardev/char-udp.c | 26 ++--
chardev/char.c | 161 +++++++++++------------
gdbstub.c | 2 +-
hw/bt/hci-csr.c | 2 +-
qom/container.c | 1 +
tests/test-char.c | 358 +++++++++++++++++++++++++++++++++++++++++++++++++-
ui/console.c | 2 +-
ui/gtk.c | 2 +-
vl.c | 2 +-
xen-common.c | 2 +-
16 files changed, 510 insertions(+), 125 deletions(-)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 01/22] char: remove qemu_chr_be_generic_open
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 02/22] mux: simplfy muxes_realize_done Marc-André Lureau
` (20 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
The function simply alias and hides the real event function.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/sysemu/char.h | 1 -
chardev/char-pty.c | 2 +-
chardev/char-socket.c | 2 +-
chardev/char.c | 10 ++--------
ui/console.c | 2 +-
ui/gtk.c | 2 +-
6 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 450881d42c..a30ff3fa80 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -427,7 +427,6 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
*/
void qemu_chr_fe_take_focus(CharBackend *b);
-void qemu_chr_be_generic_open(Chardev *s);
void qemu_chr_fe_accept_input(CharBackend *be);
int qemu_chr_add_client(Chardev *s, int fd);
Chardev *qemu_chr_find(const char *name);
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 27eb85f505..3756310f0c 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -185,7 +185,7 @@ static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
PtyChardev *s = PTY_CHARDEV(opaque);
s->open_tag = 0;
- qemu_chr_be_generic_open(chr);
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
return FALSE;
}
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 4068dc5e52..00b7de3cc4 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -476,7 +476,7 @@ static void tcp_chr_connect(void *opaque)
tcp_chr_read,
chr, NULL);
}
- qemu_chr_be_generic_open(chr);
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
static void tcp_chr_update_read_handler(Chardev *chr,
diff --git a/chardev/char.c b/chardev/char.c
index abd525f75e..cec7224b98 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -66,12 +66,6 @@ void qemu_chr_be_event(Chardev *s, int event)
be->chr_event(be->opaque, event);
}
-void qemu_chr_be_generic_open(Chardev *s)
-{
- qemu_chr_be_event(s, CHR_EVENT_OPENED);
-}
-
-
/* Not reporting errors from writing to logfile, as logs are
* defined to be "best effort" only */
static void qemu_chr_fe_write_log(Chardev *s,
@@ -469,7 +463,7 @@ static void muxes_realize_done(Notifier *notifier, void *unused)
/* mark mux as OPENED so any new FEs will immediately receive
* OPENED event
*/
- qemu_chr_be_generic_open(chr);
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
}
muxes_realized = true;
@@ -581,7 +575,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
/* We're connecting to an already opened device, so let's make sure we
also get the open event */
if (s->be_open) {
- qemu_chr_be_generic_open(s);
+ qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
}
diff --git a/ui/console.c b/ui/console.c
index 49d0740b40..992f35a5e7 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2056,7 +2056,7 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds)
s->t_attrib = s->t_attrib_default;
}
- qemu_chr_be_generic_open(chr);
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
static void vc_chr_open(Chardev *chr,
diff --git a/ui/gtk.c b/ui/gtk.c
index f21e9e7f7b..08cac2f47b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1867,7 +1867,7 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), vc->tab_item,
gtk_label_new(vc->label));
- qemu_chr_be_generic_open(vc->vte.chr);
+ qemu_chr_be_event(vc->vte.chr, CHR_EVENT_OPENED);
return group;
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 02/22] mux: simplfy muxes_realize_done
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 01/22] char: remove qemu_chr_be_generic_open Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 03/22] xen: use a better chardev type check Marc-André Lureau
` (19 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
mux_chr_event() already send events to all backends, rename it,
export it, and use it from muxes_realize_done. This should help abstract
away mux implementation.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-mux.h | 2 +-
chardev/char-mux.c | 11 ++++++++---
chardev/char.c | 9 ++-------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/chardev/char-mux.h b/chardev/char-mux.h
index 9a2fffce91..3f41dfcfd2 100644
--- a/chardev/char-mux.h
+++ b/chardev/char-mux.h
@@ -58,6 +58,6 @@ typedef struct MuxChardev {
void mux_chr_set_handlers(Chardev *chr, GMainContext *context);
void mux_set_focus(Chardev *chr, int focus);
-void mux_chr_send_event(MuxChardev *d, int mux_nr, int event);
+void mux_chr_send_all_event(Chardev *chr, int event);
#endif /* CHAR_MUX_H */
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 5547a36a0a..37d42c65c6 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -114,7 +114,7 @@ static void mux_print_help(Chardev *chr)
}
}
-void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
+static void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
{
CharBackend *be = d->backends[mux_nr];
@@ -222,9 +222,9 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
bool muxes_realized;
-static void mux_chr_event(void *opaque, int event)
+void mux_chr_send_all_event(Chardev *chr, int event)
{
- MuxChardev *d = MUX_CHARDEV(opaque);
+ MuxChardev *d = MUX_CHARDEV(chr);
int i;
if (!muxes_realized) {
@@ -237,6 +237,11 @@ static void mux_chr_event(void *opaque, int event)
}
}
+static void mux_chr_event(void *opaque, int event)
+{
+ mux_chr_send_all_event(CHARDEV(opaque), event);
+}
+
static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
{
MuxChardev *d = MUX_CHARDEV(s);
diff --git a/chardev/char.c b/chardev/char.c
index cec7224b98..9f02c6d5f1 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -451,22 +451,17 @@ static void muxes_realize_done(Notifier *notifier, void *unused)
{
Chardev *chr;
+ muxes_realized = true;
QTAILQ_FOREACH(chr, &chardevs, next) {
if (CHARDEV_IS_MUX(chr)) {
- MuxChardev *d = MUX_CHARDEV(chr);
- int i;
-
/* send OPENED to all already-attached FEs */
- for (i = 0; i < d->mux_cnt; i++) {
- mux_chr_send_event(d, i, CHR_EVENT_OPENED);
- }
+ mux_chr_send_all_event(CHARDEV(chr), CHR_EVENT_OPENED);
/* mark mux as OPENED so any new FEs will immediately receive
* OPENED event
*/
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
}
- muxes_realized = true;
}
static Notifier muxes_realize_notify = {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 03/22] xen: use a better chardev type check
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 01/22] char: remove qemu_chr_be_generic_open Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 02/22] mux: simplfy muxes_realize_done Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 04/22] container: don't leak container reference Marc-André Lureau
` (18 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
xen-common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen-common.c b/xen-common.c
index fd2c92847e..d46685ef4e 100644
--- a/xen-common.c
+++ b/xen-common.c
@@ -34,7 +34,7 @@ static int store_dev_info(int domid, Chardev *cs, const char *string)
int ret = -1;
/* Only continue if we're talking to a pty. */
- if (strncmp(cs->filename, "pty:", 4)) {
+ if (!CHARDEV_IS_PTY(cs)) {
return 0;
}
pts = cs->filename + 4;
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 04/22] container: don't leak container reference
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (2 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 03/22] xen: use a better chardev type check Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 05/22] main: free root container Marc-André Lureau
` (17 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
object_property_add_child() references the child, unref it after to
avoid ref leaks.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qom/container.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/qom/container.c b/qom/container.c
index c9eb49b01e..f6ccaf7ea7 100644
--- a/qom/container.c
+++ b/qom/container.c
@@ -40,6 +40,7 @@ Object *container_get(Object *root, const char *path)
if (!child) {
child = object_new("container");
object_property_add_child(obj, parts[i], child, NULL);
+ object_unref(child);
}
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 05/22] main: free root container
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (3 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 04/22] container: don't leak container reference Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-06 9:03 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 06/22] char: add a /chardevs container Marc-André Lureau
` (16 subsequent siblings)
21 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
This should eventually free all objects that are only referenced by
their parents.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
vl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/vl.c b/vl.c
index 0b72b12878..945df1d17f 100644
--- a/vl.c
+++ b/vl.c
@@ -4640,6 +4640,7 @@ int main(int argc, char **argv, char **envp)
audio_cleanup();
monitor_cleanup();
qemu_chr_cleanup();
+ object_unref(object_get_root());
return 0;
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (4 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 05/22] main: free root container Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-06 9:05 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 07/22] char: use /chardevs container instead of chardevs list Marc-André Lureau
` (15 subsequent siblings)
21 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Add a /chardevs container object to hold the list of chardevs.
(Note: QTAILQ chardevs is going away in the following commits)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/sysemu/char.h | 3 ++-
chardev/char.c | 46 ++++++++++++++++++++++++++++++++++++++--------
gdbstub.c | 2 +-
hw/bt/hci-csr.c | 2 +-
4 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index a30ff3fa80..e3f3a10d17 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -490,7 +490,8 @@ typedef struct ChardevClass {
} ChardevClass;
Chardev *qemu_chardev_new(const char *id, const char *typename,
- ChardevBackend *backend, Error **errp);
+ ChardevBackend *backend, bool enlist,
+ Error **errp);
extern int term_escape_char;
diff --git a/chardev/char.c b/chardev/char.c
index 9f02c6d5f1..5a12a79c3b 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -45,6 +45,11 @@
static QTAILQ_HEAD(ChardevHead, Chardev) chardevs =
QTAILQ_HEAD_INITIALIZER(chardevs);
+static Object *get_chardevs_root(void)
+{
+ return container_get(object_get_root(), "/chardevs");
+}
+
void qemu_chr_be_event(Chardev *s, int event)
{
CharBackend *be = s->be;
@@ -804,7 +809,7 @@ static Chardev *qemu_chardev_add(const char *id, const char *typename,
return NULL;
}
- chr = qemu_chardev_new(id, typename, backend, errp);
+ chr = qemu_chardev_new(id, typename, backend, true, errp);
if (!chr) {
return NULL;
}
@@ -1061,8 +1066,14 @@ void qemu_chr_fe_disconnect(CharBackend *be)
void qemu_chr_delete(Chardev *chr)
{
- QTAILQ_REMOVE(&chardevs, chr, next);
- object_unref(OBJECT(chr));
+ if (QTAILQ_IN_USE(chr, next)) {
+ QTAILQ_REMOVE(&chardevs, chr, next);
+ }
+ if (OBJECT(chr)->parent) {
+ object_unparent(OBJECT(chr));
+ } else {
+ object_unref(OBJECT(chr));
+ }
}
ChardevInfoList *qmp_query_chardev(Error **errp)
@@ -1224,22 +1235,33 @@ void qemu_chr_set_feature(Chardev *chr,
}
Chardev *qemu_chardev_new(const char *id, const char *typename,
- ChardevBackend *backend, Error **errp)
+ ChardevBackend *backend, bool enlist,
+ Error **errp)
{
+ Object *obj;
Chardev *chr = NULL;
Error *local_err = NULL;
bool be_opened = true;
assert(g_str_has_prefix(typename, "chardev-"));
- chr = CHARDEV(object_new(typename));
+ if (enlist) {
+ obj = object_new_with_props(typename, get_chardevs_root(),
+ id, &local_err, NULL);
+ } else {
+ obj = object_new(typename);
+ }
+ if (local_err) {
+ assert(!obj);
+ goto end;
+ }
+
+ chr = CHARDEV(obj);
chr->label = g_strdup(id);
qemu_char_open(chr, backend, &be_opened, &local_err);
if (local_err) {
- error_propagate(errp, local_err);
- object_unref(OBJECT(chr));
- return NULL;
+ goto end;
}
if (!chr->filename) {
@@ -1249,6 +1271,14 @@ Chardev *qemu_chardev_new(const char *id, const char *typename,
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
+end:
+ if (local_err) {
+ error_propagate(errp, local_err);
+ if (chr) {
+ qemu_chr_delete(chr);
+ }
+ return NULL;
+ }
return chr;
}
diff --git a/gdbstub.c b/gdbstub.c
index 755a8e378d..613ac48fed 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1793,7 +1793,7 @@ int gdbserver_start(const char *device)
/* Initialize a monitor terminal for gdb */
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
- NULL, &error_abort);
+ NULL, false, &error_abort);
monitor_init(mon_chr, 0);
} else {
if (qemu_chr_fe_get_driver(&s->chr)) {
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
index 3c193848fc..9c211e89c4 100644
--- a/hw/bt/hci-csr.c
+++ b/hw/bt/hci-csr.c
@@ -503,7 +503,7 @@ static const TypeInfo char_hci_type_info = {
Chardev *uart_hci_init(void)
{
return qemu_chardev_new(NULL, TYPE_CHARDEV_HCI,
- NULL, &error_abort);
+ NULL, false, &error_abort);
}
static void register_types(void)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 07/22] char: use /chardevs container instead of chardevs list
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (5 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 06/22] char: add a /chardevs container Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 08/22] char: remove qemu_chardev_add Marc-André Lureau
` (14 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Use object_resolve_path_component() and object_child_foreach() on
/chardevs container instead of iterating over chardevs list.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char.c | 66 ++++++++++++++++++++++++++++++++--------------------------
1 file changed, 36 insertions(+), 30 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index 5a12a79c3b..bdba808188 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -452,21 +452,24 @@ static const TypeInfo char_type_info = {
* mux will receive CHR_EVENT_OPENED notifications for the BE
* immediately.
*/
-static void muxes_realize_done(Notifier *notifier, void *unused)
+static int open_muxes(Object *child, void *opaque)
{
- Chardev *chr;
+ if (CHARDEV_IS_MUX(child)) {
+ /* send OPENED to all already-attached FEs */
+ mux_chr_send_all_event(CHARDEV(child), CHR_EVENT_OPENED);
+ /* mark mux as OPENED so any new FEs will immediately receive
+ * OPENED event
+ */
+ qemu_chr_be_event(CHARDEV(child), CHR_EVENT_OPENED);
+ }
+ return 0;
+}
+
+static void muxes_realize_done(Notifier *notifier, void *unused)
+{
muxes_realized = true;
- QTAILQ_FOREACH(chr, &chardevs, next) {
- if (CHARDEV_IS_MUX(chr)) {
- /* send OPENED to all already-attached FEs */
- mux_chr_send_all_event(CHARDEV(chr), CHR_EVENT_OPENED);
- /* mark mux as OPENED so any new FEs will immediately receive
- * OPENED event
- */
- qemu_chr_be_event(chr, CHR_EVENT_OPENED);
- }
- }
+ object_child_foreach(get_chardevs_root(), open_muxes, NULL);
}
static Notifier muxes_realize_notify = {
@@ -1076,21 +1079,29 @@ void qemu_chr_delete(Chardev *chr)
}
}
+static int qmp_query_chardev_foreach(Object *obj, void *data)
+{
+ Chardev *chr = CHARDEV(obj);
+ ChardevInfoList **list = data;
+ ChardevInfoList *info = g_malloc0(sizeof(*info));
+
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->label = g_strdup(chr->label);
+ info->value->filename = g_strdup(chr->filename);
+ info->value->frontend_open = chr->be && chr->be->fe_open;
+
+ info->next = *list;
+ *list = info;
+
+ return 0;
+}
+
ChardevInfoList *qmp_query_chardev(Error **errp)
{
ChardevInfoList *chr_list = NULL;
- Chardev *chr;
-
- QTAILQ_FOREACH(chr, &chardevs, next) {
- ChardevInfoList *info = g_malloc0(sizeof(*info));
- info->value = g_malloc0(sizeof(*info->value));
- info->value->label = g_strdup(chr->label);
- info->value->filename = g_strdup(chr->filename);
- info->value->frontend_open = chr->be && chr->be->fe_open;
- info->next = chr_list;
- chr_list = info;
- }
+ object_child_foreach(get_chardevs_root(),
+ qmp_query_chardev_foreach, &chr_list);
return chr_list;
}
@@ -1118,14 +1129,9 @@ ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
Chardev *qemu_chr_find(const char *name)
{
- Chardev *chr;
+ Object *obj = object_resolve_path_component(get_chardevs_root(), name);
- QTAILQ_FOREACH(chr, &chardevs, next) {
- if (strcmp(chr->label, name) != 0)
- continue;
- return chr;
- }
- return NULL;
+ return obj ? CHARDEV(obj) : NULL;
}
QemuOptsList qemu_chardev_opts = {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 08/22] char: remove qemu_chardev_add
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (6 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 07/22] char: use /chardevs container instead of chardevs list Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 09/22] char: remove chardevs list Marc-André Lureau
` (13 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
qemu_chardev_new() now uses object_new_with_props() with /chardevs
parent container. It will fail to insert the object if the same "id"
already exists. "chardevs" list usage has been removed in previous
commits.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char.c | 31 ++++++-------------------------
1 file changed, 6 insertions(+), 25 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index bdba808188..1103b08177 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -801,26 +801,6 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
return cc;
}
-static Chardev *qemu_chardev_add(const char *id, const char *typename,
- ChardevBackend *backend, Error **errp)
-{
- Chardev *chr;
-
- chr = qemu_chr_find(id);
- if (chr) {
- error_setg(errp, "Chardev '%s' already exists", id);
- return NULL;
- }
-
- chr = qemu_chardev_new(id, typename, backend, true, errp);
- if (!chr) {
- return NULL;
- }
-
- QTAILQ_INSERT_TAIL(&chardevs, chr, next);
- return chr;
-}
-
static const struct ChardevAlias {
const char *typename;
const char *alias;
@@ -937,9 +917,10 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
backend->u.null.data = ccom; /* Any ChardevCommon member would work */
}
- chr = qemu_chardev_add(bid ? bid : id,
+ chr = qemu_chardev_new(bid ? bid : id,
object_class_get_name(OBJECT_CLASS(cc)),
- backend, errp);
+ backend, true, errp);
+
if (chr == NULL) {
goto out;
}
@@ -951,7 +932,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
backend->type = CHARDEV_BACKEND_KIND_MUX;
backend->u.mux.data = g_new0(ChardevMux, 1);
backend->u.mux.data->chardev = g_strdup(bid);
- mux = qemu_chardev_add(id, TYPE_CHARDEV_MUX, backend, errp);
+ mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, true, errp);
if (mux == NULL) {
qemu_chr_delete(chr);
chr = NULL;
@@ -1300,8 +1281,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
return NULL;
}
- chr = qemu_chardev_add(id, object_class_get_name(OBJECT_CLASS(cc)),
- backend, errp);
+ chr = qemu_chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
+ backend, true, errp);
if (!chr) {
return NULL;
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 09/22] char: remove chardevs list
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (7 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 08/22] char: remove qemu_chardev_add Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 10/22] char: useless NULL check Marc-André Lureau
` (12 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
The list is now empty, the chardev cleanup is taken care of by the unref
of the root container.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/sysemu/char.h | 8 --------
chardev/char.c | 15 ---------------
vl.c | 1 -
3 files changed, 24 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index e3f3a10d17..e273c94421 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -95,7 +95,6 @@ struct Chardev {
int be_open;
guint fd_in_tag;
DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST);
- QTAILQ_ENTRY(Chardev) next;
};
/**
@@ -142,13 +141,6 @@ Chardev *qemu_chr_new(const char *label, const char *filename);
void qemu_chr_fe_disconnect(CharBackend *be);
/**
- * @qemu_chr_cleanup:
- *
- * Delete all chardevs (when leaving qemu)
- */
-void qemu_chr_cleanup(void);
-
-/**
* @qemu_chr_fe_wait_connected:
*
* Wait for characted backend to be connected, return < 0 on error or
diff --git a/chardev/char.c b/chardev/char.c
index 1103b08177..f47d933828 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -42,9 +42,6 @@
/***********************************************************/
/* character device */
-static QTAILQ_HEAD(ChardevHead, Chardev) chardevs =
- QTAILQ_HEAD_INITIALIZER(chardevs);
-
static Object *get_chardevs_root(void)
{
return container_get(object_get_root(), "/chardevs");
@@ -1050,9 +1047,6 @@ void qemu_chr_fe_disconnect(CharBackend *be)
void qemu_chr_delete(Chardev *chr)
{
- if (QTAILQ_IN_USE(chr, next)) {
- QTAILQ_REMOVE(&chardevs, chr, next);
- }
if (OBJECT(chr)->parent) {
object_unparent(OBJECT(chr));
} else {
@@ -1317,15 +1311,6 @@ void qmp_chardev_remove(const char *id, Error **errp)
qemu_chr_delete(chr);
}
-void qemu_chr_cleanup(void)
-{
- Chardev *chr, *tmp;
-
- QTAILQ_FOREACH_SAFE(chr, &chardevs, next, tmp) {
- qemu_chr_delete(chr);
- }
-}
-
static void register_types(void)
{
type_register_static(&char_type_info);
diff --git a/vl.c b/vl.c
index 945df1d17f..7bce3b07e2 100644
--- a/vl.c
+++ b/vl.c
@@ -4639,7 +4639,6 @@ int main(int argc, char **argv, char **envp)
net_cleanup();
audio_cleanup();
monitor_cleanup();
- qemu_chr_cleanup();
object_unref(object_get_root());
return 0;
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 10/22] char: useless NULL check
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (8 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 09/22] char: remove chardevs list Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 11/22] qcow2: remove " Marc-André Lureau
` (11 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
g_strdup(NULL) returns NULL already.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/chardev/char.c b/chardev/char.c
index f47d933828..4b633b9366 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -763,7 +763,7 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
const char *logfile = qemu_opt_get(opts, "logfile");
backend->has_logfile = logfile != NULL;
- backend->logfile = logfile ? g_strdup(logfile) : NULL;
+ backend->logfile = g_strdup(logfile);
backend->has_logappend = true;
backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 11/22] qcow2: remove useless NULL check
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (9 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 10/22] char: useless NULL check Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-06 9:06 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 12/22] char-socket: introduce update_disconnected_filename() Marc-André Lureau
` (10 subsequent siblings)
21 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
g_strdup() already handles the case where the argument is NULL.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
block/qcow2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 96fb8a8f16..9114218030 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2016,8 +2016,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
g_free(s->image_backing_file);
g_free(s->image_backing_format);
- s->image_backing_file = backing_file ? g_strdup(bs->backing_file) : NULL;
- s->image_backing_format = backing_fmt ? g_strdup(bs->backing_format) : NULL;
+ s->image_backing_file = g_strdup(bs->backing_file);
+ s->image_backing_format = g_strdup(bs->backing_format);
return qcow2_update_header(bs);
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 12/22] char-socket: introduce update_disconnected_filename()
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (10 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 11/22] qcow2: remove " Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 13/22] char-socket: update local address after listen Marc-André Lureau
` (9 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
This helper will be used in yet another place in the following patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-socket.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 00b7de3cc4..1f2377bb4e 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -353,6 +353,15 @@ static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
}
}
+static void update_disconnected_filename(SocketChardev *s)
+{
+ Chardev *chr = CHARDEV(s);
+
+ g_free(chr->filename);
+ chr->filename = SocketAddress_to_str("disconnected:", s->addr,
+ s->is_listen, s->is_telnet);
+}
+
static void tcp_chr_disconnect(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
@@ -367,8 +376,7 @@ static void tcp_chr_disconnect(Chardev *chr)
s->listen_tag = qio_channel_add_watch(
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
}
- chr->filename = SocketAddress_to_str("disconnected:", s->addr,
- s->is_listen, s->is_telnet);
+ update_disconnected_filename(s);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
if (s->reconnect_time) {
qemu_chr_socket_restart_timer(chr);
@@ -862,8 +870,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
/* be isn't opened until we get a connection */
*be_opened = false;
- chr->filename = SocketAddress_to_str("disconnected:",
- addr, is_listen, is_telnet);
+ update_disconnected_filename(s);
if (is_listen) {
if (is_telnet) {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 13/22] char-socket: update local address after listen
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (11 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 12/22] char-socket: introduce update_disconnected_filename() Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 14/22] char-socket: add 'addr' property Marc-André Lureau
` (8 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
This is mainly useful to know the actual bound port when using port 0.
For example, when starting qemu with socket on port 0, before:
QEMU waiting for connection on: disconnected:tcp:localhost:0,server
After:
QEMU waiting for connection on: disconnected:tcp:localhost:32454,server
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-socket.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 1f2377bb4e..58c60d05fe 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -898,6 +898,11 @@ static void qmp_chardev_open_socket(Chardev *chr,
if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
goto error;
}
+
+ qapi_free_SocketAddress(s->addr);
+ s->addr = socket_local_address(sioc->fd, errp);
+ update_disconnected_filename(s);
+
s->listen_ioc = sioc;
if (is_waitconnect &&
qemu_chr_wait_connected(chr, errp) < 0) {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 14/22] char-socket: add 'addr' property
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (12 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 13/22] char-socket: update local address after listen Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 15/22] char-socket: add 'connected' property Marc-André Lureau
` (7 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Add a property to lookup the connection details.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-socket.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 58c60d05fe..075d6f671d 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -996,6 +996,15 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
sock->addr = addr;
}
+static void
+char_socket_get_addr(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(obj);
+
+ visit_type_SocketAddress(v, name, &s->addr, errp);
+}
+
static void char_socket_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -1011,6 +1020,10 @@ static void char_socket_class_init(ObjectClass *oc, void *data)
cc->chr_add_client = tcp_chr_add_client;
cc->chr_add_watch = tcp_chr_add_watch;
cc->chr_update_read_handler = tcp_chr_update_read_handler;
+
+ object_class_property_add(oc, "addr", "SocketAddress",
+ char_socket_get_addr, NULL,
+ NULL, NULL, &error_abort);
}
static const TypeInfo char_socket_type_info = {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 15/22] char-socket: add 'connected' property
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (13 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 14/22] char-socket: add 'addr' property Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 16/22] char-udp: flush as much buffer as possible Marc-André Lureau
` (6 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-socket.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 075d6f671d..175cc18269 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -1005,6 +1005,14 @@ char_socket_get_addr(Object *obj, Visitor *v, const char *name,
visit_type_SocketAddress(v, name, &s->addr, errp);
}
+static bool
+char_socket_get_connected(Object *obj, Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(obj);
+
+ return s->connected;
+}
+
static void char_socket_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -1024,6 +1032,9 @@ static void char_socket_class_init(ObjectClass *oc, void *data)
object_class_property_add(oc, "addr", "SocketAddress",
char_socket_get_addr, NULL,
NULL, NULL, &error_abort);
+
+ object_class_property_add_bool(oc, "connected", char_socket_get_connected,
+ NULL, &error_abort);
}
static const TypeInfo char_socket_type_info = {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 16/22] char-udp: flush as much buffer as possible
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (14 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 15/22] char-socket: add 'connected' property Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 17/22] tests: add alias check in /char/ringbuf Marc-André Lureau
` (5 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Instead of flushing the buffer byte by byte, call qemu_chr_be_write()
with as much byte possible accepted by the front-end.
Factor out buffer flushing in a common function udp_chr_flush_buffer().
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char-udp.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index 2c6c7ddd73..5364b5fc59 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -51,6 +51,18 @@ static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len)
s->ioc, (const char *)buf, len, NULL);
}
+static void udp_chr_flush_buffer(UdpChardev *s)
+{
+ Chardev *chr = CHARDEV(s);
+
+ while (s->max_size > 0 && s->bufptr < s->bufcnt) {
+ int n = MIN(s->max_size, s->bufcnt - s->bufptr);
+ qemu_chr_be_write(chr, &s->buf[s->bufptr], n);
+ s->bufptr += n;
+ s->max_size = qemu_chr_be_can_write(chr);
+ }
+}
+
static int udp_chr_read_poll(void *opaque)
{
Chardev *chr = CHARDEV(opaque);
@@ -61,11 +73,8 @@ static int udp_chr_read_poll(void *opaque)
/* If there were any stray characters in the queue process them
* first
*/
- while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
- s->bufptr++;
- s->max_size = qemu_chr_be_can_write(chr);
- }
+ udp_chr_flush_buffer(s);
+
return s->max_size;
}
@@ -85,13 +94,8 @@ static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
return FALSE;
}
s->bufcnt = ret;
-
s->bufptr = 0;
- while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
- s->bufptr++;
- s->max_size = qemu_chr_be_can_write(chr);
- }
+ udp_chr_flush_buffer(s);
return TRUE;
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 17/22] tests: add alias check in /char/ringbuf
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (15 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 16/22] char-udp: flush as much buffer as possible Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 18/22] tests: add /char/pipe test Marc-André Lureau
` (4 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index da69f110e4..aa9b18a61b 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -104,6 +104,16 @@ static void char_ringbuf_test(void)
qemu_chr_fe_deinit(&be);
qemu_chr_delete(chr);
+
+ /* check alias */
+ opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
+ 1, &error_abort);
+ qemu_opt_set(opts, "backend", "memory", &error_abort);
+ qemu_opt_set(opts, "size", "2", &error_abort);
+ chr = qemu_chr_new_from_opts(opts, NULL);
+ g_assert_nonnull(chr);
+ qemu_chr_delete(chr);
+ qemu_opts_del(opts);
}
static void char_mux_test(void)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 18/22] tests: add /char/pipe test
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (16 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 17/22] tests: add alias check in /char/ringbuf Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 19/22] tests: add /char/file test Marc-André Lureau
` (3 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index aa9b18a61b..8166ace487 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -1,4 +1,5 @@
#include "qemu/osdep.h"
+#include <glib/gstdio.h>
#include "qemu-common.h"
#include "qemu/config-file.h"
@@ -7,12 +8,28 @@
#include "qapi/error.h"
#include "qmp-commands.h"
+static bool quit;
+
typedef struct FeHandler {
int read_count;
int last_event;
char read_buf[128];
} FeHandler;
+#ifndef _WIN32
+static void main_loop(void)
+{
+ bool nonblocking;
+ int last_io = 0;
+
+ quit = false;
+ do {
+ nonblocking = last_io > 0;
+ last_io = main_loop_wait(nonblocking);
+ } while (!quit);
+}
+#endif
+
static int fe_can_read(void *opaque)
{
FeHandler *h = opaque;
@@ -28,6 +45,7 @@ static void fe_read(void *opaque, const uint8_t *buf, int size)
memcpy(h->read_buf + h->read_count, buf, size);
h->read_count += size;
+ quit = true;
}
static void fe_event(void *opaque, int event)
@@ -35,6 +53,7 @@ static void fe_event(void *opaque, int event)
FeHandler *h = opaque;
h->last_event = event;
+ quit = true;
}
#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
@@ -192,6 +211,72 @@ static void char_mux_test(void)
qemu_chr_delete(chr);
}
+#ifndef _WIN32
+static void char_pipe_test(void)
+{
+ gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
+ gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL);
+ Chardev *chr;
+ CharBackend be;
+ int ret, fd;
+ char buf[10];
+ FeHandler fe = { 0, };
+
+ in = g_strdup_printf("%s.in", pipe);
+ if (mkfifo(in, 0600) < 0) {
+ abort();
+ }
+ out = g_strdup_printf("%s.out", pipe);
+ if (mkfifo(out, 0600) < 0) {
+ abort();
+ }
+
+ tmp = g_strdup_printf("pipe:%s", pipe);
+ chr = qemu_chr_new("pipe", tmp);
+ g_assert_nonnull(chr);
+ g_free(tmp);
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+
+ ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9);
+ g_assert_cmpint(ret, ==, 9);
+
+ fd = open(out, O_RDWR);
+ ret = read(fd, buf, sizeof(buf));
+ g_assert_cmpint(ret, ==, 9);
+ g_assert_cmpstr(buf, ==, "pipe-out");
+ close(fd);
+
+ fd = open(in, O_WRONLY);
+ ret = write(fd, "pipe-in", 8);
+ g_assert_cmpint(ret, ==, 8);
+ close(fd);
+
+ qemu_chr_fe_set_handlers(&be,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ &fe,
+ NULL, true);
+
+ main_loop();
+
+ g_assert_cmpint(fe.read_count, ==, 8);
+ g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
+
+ qemu_chr_fe_deinit(&be);
+ qemu_chr_delete(chr);
+
+ g_assert(g_unlink(in) == 0);
+ g_assert(g_unlink(out) == 0);
+ g_assert(g_rmdir(tmp_path) == 0);
+ g_free(in);
+ g_free(out);
+ g_free(tmp_path);
+ g_free(pipe);
+}
+#endif
+
static void char_null_test(void)
{
Error *err = NULL;
@@ -245,6 +330,8 @@ static void char_invalid_test(void)
int main(int argc, char **argv)
{
+ qemu_init_main_loop(&error_abort);
+
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
@@ -258,6 +345,9 @@ int main(int argc, char **argv)
g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
g_test_add_func("/char/stdio", char_stdio_test);
#endif
+#ifndef _WIN32
+ g_test_add_func("/char/pipe", char_pipe_test);
+#endif
return g_test_run();
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 19/22] tests: add /char/file test
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (17 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 18/22] tests: add /char/pipe test Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 20/22] tests: add /char/socket test Marc-André Lureau
` (2 subsequent siblings)
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index 8166ace487..d543e897a0 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -277,6 +277,76 @@ static void char_pipe_test(void)
}
#endif
+static void char_file_test(void)
+{
+ char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
+ char *out = g_build_filename(tmp_path, "out", NULL);
+ char *contents = NULL;
+ ChardevFile file = { .out = out };
+ ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
+ .u.file.data = &file };
+ Chardev *chr;
+ gsize length;
+ int ret;
+
+ chr = qemu_chardev_new("file-out", TYPE_CHARDEV_FILE, &backend,
+ false, &error_abort);
+ ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
+ g_assert_cmpint(ret, ==, 6);
+ qemu_chr_delete(chr);
+
+ ret = g_file_get_contents(out, &contents, &length, NULL);
+ g_assert(ret == TRUE);
+ g_assert_cmpint(length, ==, 6);
+ g_assert(strncmp(contents, "hello!", 6) == 0);
+ g_free(contents);
+
+#ifndef _WIN32
+ {
+ CharBackend be;
+ FeHandler fe = { 0, };
+ char *fifo = g_build_filename(tmp_path, "fifo", NULL);
+ int fd;
+
+ if (mkfifo(fifo, 0600) < 0) {
+ abort();
+ }
+
+ fd = open(fifo, O_RDWR);
+ ret = write(fd, "fifo-in", 8);
+ g_assert_cmpint(ret, ==, 8);
+
+ file.in = fifo;
+ file.has_in = true;
+ chr = qemu_chardev_new("file", TYPE_CHARDEV_FILE, &backend,
+ false, &error_abort);
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&be,
+ fe_can_read,
+ fe_read,
+ fe_event,
+ &fe, NULL, true);
+
+ main_loop();
+
+ close(fd);
+
+ g_assert_cmpint(fe.read_count, ==, 8);
+ g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
+ qemu_chr_fe_deinit(&be);
+ qemu_chr_delete(chr);
+ g_unlink(fifo);
+ g_free(fifo);
+ }
+#endif
+
+ g_unlink(out);
+ g_rmdir(tmp_path);
+ g_free(tmp_path);
+ g_free(out);
+}
+
static void char_null_test(void)
{
Error *err = NULL;
@@ -348,6 +418,7 @@ int main(int argc, char **argv)
#ifndef _WIN32
g_test_add_func("/char/pipe", char_pipe_test);
#endif
+ g_test_add_func("/char/file", char_file_test);
return g_test_run();
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 20/22] tests: add /char/socket test
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (18 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 19/22] tests: add /char/file test Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 21/22] tests: add /char/udp test Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 22/22] tests: add /char/console test Marc-André Lureau
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 2 deletions(-)
diff --git a/tests/test-char.c b/tests/test-char.c
index d543e897a0..e35e301a47 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -3,9 +3,11 @@
#include "qemu-common.h"
#include "qemu/config-file.h"
+#include "qemu/sockets.h"
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "qapi/error.h"
+#include "qom/qom-qobject.h"
#include "qmp-commands.h"
static bool quit;
@@ -16,7 +18,6 @@ typedef struct FeHandler {
char read_buf[128];
} FeHandler;
-#ifndef _WIN32
static void main_loop(void)
{
bool nonblocking;
@@ -28,7 +29,6 @@ static void main_loop(void)
last_io = main_loop_wait(nonblocking);
} while (!quit);
}
-#endif
static int fe_can_read(void *opaque)
{
@@ -211,6 +211,114 @@ static void char_mux_test(void)
qemu_chr_delete(chr);
}
+typedef struct SocketIdleData {
+ GMainLoop *loop;
+ Chardev *chr;
+ bool conn_expected;
+ CharBackend *be;
+ CharBackend *client_be;
+} SocketIdleData;
+
+static gboolean char_socket_test_idle(gpointer user_data)
+{
+ SocketIdleData *data = user_data;
+
+ if (object_property_get_bool(OBJECT(data->chr), "connected", NULL)
+ == data->conn_expected) {
+ quit = true;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void socket_read(void *opaque, const uint8_t *buf, int size)
+{
+ SocketIdleData *data = opaque;
+
+ g_assert_cmpint(size, ==, 1);
+ g_assert_cmpint(*buf, ==, 'Z');
+
+ size = qemu_chr_fe_write(data->be, (const uint8_t *)"hello", 5);
+ g_assert_cmpint(size, ==, 5);
+}
+
+static int socket_can_read(void *opaque)
+{
+ return 10;
+}
+
+static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
+{
+ g_assert_cmpint(size, ==, 5);
+ g_assert(strncmp((char *)buf, "hello", 5) == 0);
+
+ quit = true;
+}
+
+static int socket_can_read_hello(void *opaque)
+{
+ return 10;
+}
+
+static void char_socket_test(void)
+{
+ Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
+ Chardev *chr_client;
+ QObject *addr;
+ QDict *qdict, *data;
+ const char *port;
+ SocketIdleData d = { .chr = chr };
+ CharBackend be;
+ CharBackend client_be;
+ char *tmp;
+
+ d.be = &be;
+ d.client_be = &be;
+
+ g_assert_nonnull(chr);
+ g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+
+ addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
+ qdict = qobject_to_qdict(addr);
+ data = qdict_get_qdict(qdict, "data");
+ port = qdict_get_str(data, "port");
+ tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
+ QDECREF(qdict);
+
+ qemu_chr_fe_init(&be, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read,
+ NULL, &d, NULL, true);
+
+ chr_client = qemu_chr_new("client", tmp);
+ qemu_chr_fe_init(&client_be, chr_client, &error_abort);
+ qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello,
+ socket_read_hello,
+ NULL, &d, NULL, true);
+ g_free(tmp);
+
+ d.conn_expected = true;
+ guint id = g_idle_add(char_socket_test_idle, &d);
+ g_source_set_name_by_id(id, "test-idle");
+ g_assert_cmpint(id, >, 0);
+ main_loop();
+
+ g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
+ g_assert(object_property_get_bool(OBJECT(chr_client),
+ "connected", &error_abort));
+
+ qemu_chr_write_all(chr_client, (const uint8_t *)"Z", 1);
+ main_loop();
+
+ qemu_chr_delete(chr_client);
+
+ d.conn_expected = false;
+ g_idle_add(char_socket_test_idle, &d);
+ main_loop();
+
+ qemu_chr_delete(chr);
+}
+
#ifndef _WIN32
static void char_pipe_test(void)
{
@@ -401,6 +509,7 @@ static void char_invalid_test(void)
int main(int argc, char **argv)
{
qemu_init_main_loop(&error_abort);
+ socket_init();
g_test_init(&argc, &argv, NULL);
@@ -419,6 +528,7 @@ int main(int argc, char **argv)
g_test_add_func("/char/pipe", char_pipe_test);
#endif
g_test_add_func("/char/file", char_file_test);
+ g_test_add_func("/char/socket", char_socket_test);
return g_test_run();
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 21/22] tests: add /char/udp test
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (19 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 20/22] tests: add /char/socket test Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 22/22] tests: add /char/console test Marc-André Lureau
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/tests/test-char.c b/tests/test-char.c
index e35e301a47..df2695e75d 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -385,6 +385,51 @@ static void char_pipe_test(void)
}
#endif
+static void char_udp_test(void)
+{
+ struct sockaddr_in addr = { 0, }, other;
+ SocketIdleData d = { 0, };
+ Chardev *chr;
+ CharBackend be;
+ socklen_t alen = sizeof(addr);
+ int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0);
+ char buf[10];
+ char *tmp;
+
+ g_assert_cmpint(sock, >, 0);
+ addr.sin_family = AF_INET ;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+ ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+ g_assert_cmpint(ret, ==, 0);
+ ret = getsockname(sock, (struct sockaddr *)&addr, &alen);
+ g_assert_cmpint(ret, ==, 0);
+
+ tmp = g_strdup_printf("udp:127.0.0.1:%d",
+ ntohs(addr.sin_port));
+ chr = qemu_chr_new("client", tmp);
+ g_assert_nonnull(chr);
+
+ d.chr = chr;
+ qemu_chr_fe_init(&be, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&be, socket_can_read_hello, socket_read_hello,
+ NULL, &d, NULL, true);
+ ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
+ g_assert_cmpint(ret, ==, 5);
+
+ alen = sizeof(addr);
+ ret = recvfrom(sock, buf, sizeof(buf), 0,
+ (struct sockaddr *)&other, &alen);
+ g_assert_cmpint(ret, ==, 5);
+ ret = sendto(sock, buf, 5, 0, (struct sockaddr *)&other, alen);
+ g_assert_cmpint(ret, ==, 5);
+
+ main_loop();
+
+ close(sock);
+ g_free(tmp);
+}
+
static void char_file_test(void)
{
char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
@@ -529,6 +574,7 @@ int main(int argc, char **argv)
#endif
g_test_add_func("/char/file", char_file_test);
g_test_add_func("/char/socket", char_socket_test);
+ g_test_add_func("/char/udp", char_udp_test);
return g_test_run();
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [Qemu-devel] [PATCH 22/22] tests: add /char/console test
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
` (20 preceding siblings ...)
2017-02-02 14:51 ` [Qemu-devel] [PATCH 21/22] tests: add /char/udp test Marc-André Lureau
@ 2017-02-02 14:51 ` Marc-André Lureau
21 siblings, 0 replies; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-02 14:51 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, eblake, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/test-char.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/tests/test-char.c b/tests/test-char.c
index df2695e75d..5eeed4dae8 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -57,6 +57,32 @@ static void fe_event(void *opaque, int event)
}
#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+#ifdef _WIN32
+static void char_console_test_subprocess(void)
+{
+ QemuOpts *opts;
+ Chardev *chr;
+
+ opts = qemu_opts_create(qemu_find_opts("chardev"), "console-label",
+ 1, &error_abort);
+ qemu_opt_set(opts, "backend", "console", &error_abort);
+
+ chr = qemu_chr_new_from_opts(opts, NULL);
+ g_assert_nonnull(chr);
+
+ qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7);
+
+ qemu_opts_del(opts);
+ qemu_chr_delete(chr);
+}
+
+static void char_console_test(void)
+{
+ g_test_trap_subprocess("/char/console/subprocess", 0, 0);
+ g_test_trap_assert_passed();
+ g_test_trap_assert_stdout("CONSOLE");
+}
+#endif
static void char_stdio_test_subprocess(void)
{
Chardev *chr;
@@ -83,7 +109,6 @@ static void char_stdio_test(void)
}
#endif
-
static void char_ringbuf_test(void)
{
QemuOpts *opts;
@@ -566,6 +591,10 @@ int main(int argc, char **argv)
g_test_add_func("/char/ringbuf", char_ringbuf_test);
g_test_add_func("/char/mux", char_mux_test);
#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+#ifdef _WIN32
+ g_test_add_func("/char/console/subprocess", char_console_test_subprocess);
+ g_test_add_func("/char/console", char_console_test);
+#endif
g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
g_test_add_func("/char/stdio", char_stdio_test);
#endif
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 05/22] main: free root container
2017-02-02 14:51 ` [Qemu-devel] [PATCH 05/22] main: free root container Marc-André Lureau
@ 2017-02-06 9:03 ` Paolo Bonzini
2017-02-07 20:01 ` Marc-André Lureau
0 siblings, 1 reply; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-06 9:03 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 02/02/2017 15:51, Marc-André Lureau wrote:
> This should eventually free all objects that are only referenced by
> their parents.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> vl.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/vl.c b/vl.c
> index 0b72b12878..945df1d17f 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -4640,6 +4640,7 @@ int main(int argc, char **argv, char **envp)
> audio_cleanup();
> monitor_cleanup();
> qemu_chr_cleanup();
> + object_unref(object_get_root());
This seems dangerous. I'm pretty sure that a lot of non-hot-unpluggable
devices would leak or crash.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-02 14:51 ` [Qemu-devel] [PATCH 06/22] char: add a /chardevs container Marc-André Lureau
@ 2017-02-06 9:05 ` Paolo Bonzini
2017-02-07 20:03 ` Marc-André Lureau
0 siblings, 1 reply; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-06 9:05 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 02/02/2017 15:51, Marc-André Lureau wrote:
> + if (QTAILQ_IN_USE(chr, next)) {
> + QTAILQ_REMOVE(&chardevs, chr, next);
> + }
> + if (OBJECT(chr)->parent) {
> + object_unparent(OBJECT(chr));
> + } else {
> + object_unref(OBJECT(chr));
> + }
What's the case where the "else" is used? Probably qemu_chr_delete
callers should be changed to use object_unparent or object_unref directly.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 11/22] qcow2: remove useless NULL check
2017-02-02 14:51 ` [Qemu-devel] [PATCH 11/22] qcow2: remove " Marc-André Lureau
@ 2017-02-06 9:06 ` Paolo Bonzini
0 siblings, 0 replies; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-06 9:06 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 02/02/2017 15:51, Marc-André Lureau wrote:
> g_strdup() already handles the case where the argument is NULL.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> block/qcow2.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 96fb8a8f16..9114218030 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -2016,8 +2016,8 @@ static int qcow2_change_backing_file(BlockDriverState *bs,
> g_free(s->image_backing_file);
> g_free(s->image_backing_format);
>
> - s->image_backing_file = backing_file ? g_strdup(bs->backing_file) : NULL;
> - s->image_backing_format = backing_fmt ? g_strdup(bs->backing_format) : NULL;
> + s->image_backing_file = g_strdup(bs->backing_file);
> + s->image_backing_format = g_strdup(bs->backing_format);
>
> return qcow2_update_header(bs);
> }
>
Please send this separately with Cc to qemu-trivial.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 05/22] main: free root container
2017-02-06 9:03 ` Paolo Bonzini
@ 2017-02-07 20:01 ` Marc-André Lureau
2017-02-09 17:09 ` Paolo Bonzini
0 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-07 20:01 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Marc-André Lureau, qemu-devel, eblake
Hi
----- Original Message -----
>
>
> On 02/02/2017 15:51, Marc-André Lureau wrote:
> > This should eventually free all objects that are only referenced by
> > their parents.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > vl.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/vl.c b/vl.c
> > index 0b72b12878..945df1d17f 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -4640,6 +4640,7 @@ int main(int argc, char **argv, char **envp)
> > audio_cleanup();
> > monitor_cleanup();
> > qemu_chr_cleanup();
> > + object_unref(object_get_root());
>
> This seems dangerous. I'm pretty sure that a lot of non-hot-unpluggable
> devices would leak or crash.
make check is ok. Any suggestion what else to check?
This patch was added so that /chardevs container is cleaned up (with the following patches). Perhaps I could be more conservative and only unref (oops unparent) /chardevs.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-06 9:05 ` Paolo Bonzini
@ 2017-02-07 20:03 ` Marc-André Lureau
2017-02-09 17:16 ` Paolo Bonzini
0 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-07 20:03 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Marc-André Lureau, qemu-devel, eblake
Hi
----- Original Message -----
>
>
> On 02/02/2017 15:51, Marc-André Lureau wrote:
> > + if (QTAILQ_IN_USE(chr, next)) {
> > + QTAILQ_REMOVE(&chardevs, chr, next);
> > + }
> > + if (OBJECT(chr)->parent) {
> > + object_unparent(OBJECT(chr));
> > + } else {
> > + object_unref(OBJECT(chr));
> > + }
>
> What's the case where the "else" is used? Probably qemu_chr_delete
> callers should be changed to use object_unparent or object_unref directly.
I thought about that, but calling object_unparent() seems weird, since callers aren't much aware of the fact that chardev are added or not to a container (useless distinction imho). I wish the last object_unref() would automatically unparent, if the object has a parent. Would that be acceptable?
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 05/22] main: free root container
2017-02-07 20:01 ` Marc-André Lureau
@ 2017-02-09 17:09 ` Paolo Bonzini
0 siblings, 0 replies; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-09 17:09 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Marc-André Lureau, qemu-devel, eblake
On 07/02/2017 21:01, Marc-André Lureau wrote:
> Hi
>
> ----- Original Message -----
>>
>>
>> On 02/02/2017 15:51, Marc-André Lureau wrote:
>>> This should eventually free all objects that are only referenced by
>>> their parents.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>> vl.c | 1 +
>>> 1 file changed, 1 insertion(+)
>>>
>>> diff --git a/vl.c b/vl.c
>>> index 0b72b12878..945df1d17f 100644
>>> --- a/vl.c
>>> +++ b/vl.c
>>> @@ -4640,6 +4640,7 @@ int main(int argc, char **argv, char **envp)
>>> audio_cleanup();
>>> monitor_cleanup();
>>> qemu_chr_cleanup();
>>> + object_unref(object_get_root());
>>
>> This seems dangerous. I'm pretty sure that a lot of non-hot-unpluggable
>> devices would leak or crash.
>
> make check is ok. Any suggestion what else to check?
Not sure... I would have to try with some logging to see what this
does. But it doesn't seem safe, most devices are really not meant to be
hot-removed.
> This patch was added so that /chardevs container is cleaned up (with
> the following patches). Perhaps I could be more conservative and only
> unref (oops unparent) /chardevs.
Yeah, that would work.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-07 20:03 ` Marc-André Lureau
@ 2017-02-09 17:16 ` Paolo Bonzini
2017-02-10 12:14 ` Marc-André Lureau
0 siblings, 1 reply; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-09 17:16 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Marc-André Lureau, qemu-devel, eblake
On 07/02/2017 21:03, Marc-André Lureau wrote:
> Hi
>
> ----- Original Message -----
>>
>>
>> On 02/02/2017 15:51, Marc-André Lureau wrote:
>>> + if (QTAILQ_IN_USE(chr, next)) {
>>> + QTAILQ_REMOVE(&chardevs, chr, next);
>>> + }
>>> + if (OBJECT(chr)->parent) {
>>> + object_unparent(OBJECT(chr));
>>> + } else {
>>> + object_unref(OBJECT(chr));
>>> + }
>>
>> What's the case where the "else" is used? Probably qemu_chr_delete
>> callers should be changed to use object_unparent or object_unref directly.
>
> I thought about that, but calling object_unparent() seems weird,
> since callers aren't much aware of the fact that chardev are added or not to a
> container (useless distinction imho). I wish the last object_unref()
> would automatically unparent, if the object has a parent. Would that be
> acceptable?
There is a distinction between the two. The idea is that unparent
removes all persistent references in the object tree, while unref only
removes transient references. So for example unparent will detach a
device from its bus. Unparent is basically exploiting the object tree
in order to simplify the handling of reference cycles.
Once you add an object with object_property_add_child, you probably
should remove any transient references you have (such as the one you got
with object_new) and from that point on use object_unparent only.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-09 17:16 ` Paolo Bonzini
@ 2017-02-10 12:14 ` Marc-André Lureau
2017-02-10 12:26 ` Paolo Bonzini
0 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-10 12:14 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
Hi
On Fri, Feb 10, 2017 at 4:18 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 07/02/2017 21:03, Marc-André Lureau wrote:
> > Hi
> >
> > ----- Original Message -----
> >>
> >>
> >> On 02/02/2017 15:51, Marc-André Lureau wrote:
> >>> + if (QTAILQ_IN_USE(chr, next)) {
> >>> + QTAILQ_REMOVE(&chardevs, chr, next);
> >>> + }
> >>> + if (OBJECT(chr)->parent) {
> >>> + object_unparent(OBJECT(chr));
> >>> + } else {
> >>> + object_unref(OBJECT(chr));
> >>> + }
> >>
> >> What's the case where the "else" is used? Probably qemu_chr_delete
> >> callers should be changed to use object_unparent or object_unref
> directly.
> >
> > I thought about that, but calling object_unparent() seems weird,
> > since callers aren't much aware of the fact that chardev are added or
> not to a
> > container (useless distinction imho). I wish the last object_unref()
> > would automatically unparent, if the object has a parent. Would that be
> > acceptable?
>
> There is a distinction between the two. The idea is that unparent
> removes all persistent references in the object tree, while unref only
> removes transient references. So for example unparent will detach a
> device from its bus. Unparent is basically exploiting the object tree
> in order to simplify the handling of reference cycles.
>
> Once you add an object with object_property_add_child, you probably
> should remove any transient references you have (such as the one you got
> with object_new) and from that point on use object_unparent only.
>
But if you unparent with the last ref, you remove the burden of knowing if
the object has been parented from the user. I don't see why that would
conflict with object_unparent(), you could still unparent(), and keep the
object referenced somewhere else. The two are not incompatible to me.
Afaik, most widget/hierarchy API work like that, the last unref will
implicitely unparent.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-10 12:14 ` Marc-André Lureau
@ 2017-02-10 12:26 ` Paolo Bonzini
2017-02-10 12:59 ` Marc-André Lureau
0 siblings, 1 reply; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-10 12:26 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On 10/02/2017 13:14, Marc-André Lureau wrote:
> Hi
>
> On Fri, Feb 10, 2017 at 4:18 AM Paolo Bonzini <pbonzini@redhat.com
> <mailto:pbonzini@redhat.com>> wrote:
>
>
>
> On 07/02/2017 21:03, Marc-André Lureau wrote:
> > Hi
> >
> > ----- Original Message -----
> >>
> >>
> >> On 02/02/2017 15:51, Marc-André Lureau wrote:
> >>> + if (QTAILQ_IN_USE(chr, next)) {
> >>> + QTAILQ_REMOVE(&chardevs, chr, next);
> >>> + }
> >>> + if (OBJECT(chr)->parent) {
> >>> + object_unparent(OBJECT(chr));
> >>> + } else {
> >>> + object_unref(OBJECT(chr));
> >>> + }
> >>
> >> What's the case where the "else" is used? Probably qemu_chr_delete
> >> callers should be changed to use object_unparent or object_unref
> directly.
> >
> > I thought about that, but calling object_unparent() seems weird,
> > since callers aren't much aware of the fact that chardev are added
> or not to a
> > container (useless distinction imho). I wish the last object_unref()
> > would automatically unparent, if the object has a parent. Would
> that be
> > acceptable?
>
> There is a distinction between the two. The idea is that unparent
> removes all persistent references in the object tree, while unref only
> removes transient references. So for example unparent will detach a
> device from its bus. Unparent is basically exploiting the object tree
> in order to simplify the handling of reference cycles.
>
> Once you add an object with object_property_add_child, you probably
> should remove any transient references you have (such as the one you got
> with object_new) and from that point on use object_unparent only.
>
>
> But if you unparent with the last ref, you remove the burden of knowing
> if the object has been parented from the user. I don't see why that
> would conflict with object_unparent(), you could still unparent(), and
> keep the object referenced somewhere else.
Isn't that exactly why you want them to be different? unparent can do
much more than unref, for example in the case of a device it will also
unrealize it and destroy all buses underneath it. Because the device
and bus have a circular reference, you cannot trigger the magic unparent
behavior just by unref'ing the device.
There are just two cases:
- destruction immediately after creation, e.g. on error: new/unref
- successful creation: new/add_child/unref, unparent when deleting
and it's simpler to remember these two than to add magic behavior.
> The two are not incompatible
> to me. Afaik, most widget/hierarchy API work like that, the last unref
> will implicitely unparent.
LibreOffice's has some similarity with QOM, search for "dispose" at
https://people.gnome.org/~michael/blog/2015-08-05-under-the-hood-5-0.html
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-10 12:26 ` Paolo Bonzini
@ 2017-02-10 12:59 ` Marc-André Lureau
2017-02-10 13:12 ` Paolo Bonzini
0 siblings, 1 reply; 34+ messages in thread
From: Marc-André Lureau @ 2017-02-10 12:59 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
Hi
On Fri, Feb 10, 2017 at 4:26 PM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> >
> > But if you unparent with the last ref, you remove the burden of knowing
> > if the object has been parented from the user. I don't see why that
> > would conflict with object_unparent(), you could still unparent(), and
> > keep the object referenced somewhere else.
>
> Isn't that exactly why you want them to be different? unparent can do
> much more than unref, for example in the case of a device it will also
> unrealize it and destroy all buses underneath it. Because the device
>
Shouldn't the last unref also unrealize/destroy everything?
> and bus have a circular reference, you cannot trigger the magic unparent
> behavior just by unref'ing the device.
>
Whoo, we have circular references on purposes? Is this lifecycle documented
somewhere? I wonder the rationale behind it.
>
> There are just two cases:
>
> - destruction immediately after creation, e.g. on error: new/unref
>
> - successful creation: new/add_child/unref, unparent when deleting
>
> and it's simpler to remember these two than to add magic behavior.
>
>
That doesn't change the problem, the user may not know if the object is
parented. So you have to pass this information along.
> > The two are not incompatible
> > to me. Afaik, most widget/hierarchy API work like that, the last unref
> > will implicitely unparent.
>
> LibreOffice's has some similarity with QOM, search for "dispose" at
> https://people.gnome.org/~michael/blog/2015-08-05-under-the-hood-5-0.html
>
> I don't see much parallel with the discussion here except that they had a
complicated model and tried to simplify it. That's what I also try to do.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [PATCH 06/22] char: add a /chardevs container
2017-02-10 12:59 ` Marc-André Lureau
@ 2017-02-10 13:12 ` Paolo Bonzini
0 siblings, 0 replies; 34+ messages in thread
From: Paolo Bonzini @ 2017-02-10 13:12 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On 10/02/2017 13:59, Marc-André Lureau wrote:
> > But if you unparent with the last ref, you remove the burden of knowing
> > if the object has been parented from the user. I don't see why that
> > would conflict with object_unparent(), you could still unparent(), and
> > keep the object referenced somewhere else.
>
> Isn't that exactly why you want them to be different? unparent can do
> much more than unref, for example in the case of a device it will also
> unrealize it and destroy all buses underneath it. Because the device
>
> Shouldn't the last unref also unrealize/destroy everything?
How could someone say they have the "last unref"? They didn't get that
reference from anywhere, the reference is owned by the parent object's
child property.
> and bus have a circular reference, you cannot trigger the magic unparent
> behavior just by unref'ing the device.
>
> Whoo, we have circular references on purposes? Is this lifecycle
> documented somewhere? I wonder the rationale behind it.
The same as Libreoffice: we had a model with no reference counting (just
"qdev_free") and we tried to adapt it to QOM's reference counting model,
in our case by exploiting the object tree.
> There are just two cases:
>
> - destruction immediately after creation, e.g. on error: new/unref
>
> - successful creation: new/add_child/unref, unparent when deleting
>
> and it's simpler to remember these two than to add magic behavior.
>
> That doesn't change the problem, the user may not know if the object is
> parented.
If the user got a reference for himself via object_ref or object_new, it
must use object_unref.
If the user wants to remove public knowledge of an object, then they
must use object_unparent. If the object is not parented, there's a
violation of QOM rules somewhere.
Paolo
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2017-02-10 13:12 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-02 14:51 [Qemu-devel] [PATCH 00/22] chardev clean-ups & tests Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 01/22] char: remove qemu_chr_be_generic_open Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 02/22] mux: simplfy muxes_realize_done Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 03/22] xen: use a better chardev type check Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 04/22] container: don't leak container reference Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 05/22] main: free root container Marc-André Lureau
2017-02-06 9:03 ` Paolo Bonzini
2017-02-07 20:01 ` Marc-André Lureau
2017-02-09 17:09 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 06/22] char: add a /chardevs container Marc-André Lureau
2017-02-06 9:05 ` Paolo Bonzini
2017-02-07 20:03 ` Marc-André Lureau
2017-02-09 17:16 ` Paolo Bonzini
2017-02-10 12:14 ` Marc-André Lureau
2017-02-10 12:26 ` Paolo Bonzini
2017-02-10 12:59 ` Marc-André Lureau
2017-02-10 13:12 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 07/22] char: use /chardevs container instead of chardevs list Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 08/22] char: remove qemu_chardev_add Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 09/22] char: remove chardevs list Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 10/22] char: useless NULL check Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 11/22] qcow2: remove " Marc-André Lureau
2017-02-06 9:06 ` Paolo Bonzini
2017-02-02 14:51 ` [Qemu-devel] [PATCH 12/22] char-socket: introduce update_disconnected_filename() Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 13/22] char-socket: update local address after listen Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 14/22] char-socket: add 'addr' property Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 15/22] char-socket: add 'connected' property Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 16/22] char-udp: flush as much buffer as possible Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 17/22] tests: add alias check in /char/ringbuf Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 18/22] tests: add /char/pipe test Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 19/22] tests: add /char/file test Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 20/22] tests: add /char/socket test Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 21/22] tests: add /char/udp test Marc-André Lureau
2017-02-02 14:51 ` [Qemu-devel] [PATCH 22/22] tests: add /char/console test Marc-André Lureau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).