aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--monitor.c17
-rw-r--r--qemu-char.c9
-rw-r--r--qemu-options.hx35
-rw-r--r--qerror.c6
-rw-r--r--qerror.h3
-rw-r--r--sysemu.h2
-rw-r--r--vl.c33
7 files changed, 64 insertions, 41 deletions
diff --git a/monitor.c b/monitor.c
index c25d551..754bcc5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1017,7 +1017,8 @@ static void do_info_cpu_stats(Monitor *mon)
*/
static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
- exit(0);
+ monitor_suspend(mon);
+ qemu_system_exit_request();
return 0;
}
@@ -2414,15 +2415,6 @@ static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
return -1;
}
- fd = dup(fd);
- if (fd == -1) {
- if (errno == EMFILE)
- qerror_report(QERR_TOO_MANY_FILES);
- else
- qerror_report(QERR_UNDEFINED_ERROR);
- return -1;
- }
-
QLIST_FOREACH(monfd, &mon->fds, next) {
if (strcmp(monfd->name, fdname) != 0) {
continue;
@@ -4404,7 +4396,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
goto err_input;
} else if (qobject_type(obj) != QTYPE_QSTRING) {
- qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "string");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", "string");
goto err_input;
}
@@ -4437,6 +4429,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
obj = qdict_get(input, "arguments");
if (!obj) {
args = qdict_new();
+ } else if (qobject_type(obj) != QTYPE_QDICT) {
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", "object");
+ goto err_input;
} else {
args = qobject_to_qdict(obj);
QINCREF(args);
diff --git a/qemu-char.c b/qemu-char.c
index 05df971..ac65a1c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2000,8 +2000,9 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
static int tcp_get_msgfd(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
-
- return s->msgfd;
+ int fd = s->msgfd;
+ s->msgfd = -1;
+ return fd;
}
#ifndef _WIN32
@@ -2089,10 +2090,6 @@ static void tcp_chr_read(void *opaque)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
qemu_chr_read(chr, buf, size);
- if (s->msgfd != -1) {
- close(s->msgfd);
- s->msgfd = -1;
- }
}
}
diff --git a/qemu-options.hx b/qemu-options.hx
index f4b3bfe..83b54c3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1175,32 +1175,33 @@ DEFHEADING()
DEFHEADING(Character device options:)
DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
- "-chardev null,id=id\n"
+ "-chardev null,id=id[,mux=on|off]\n"
"-chardev socket,id=id[,host=host],port=host[,to=to][,ipv4][,ipv6][,nodelay]\n"
- " [,server][,nowait][,telnet] (tcp)\n"
- "-chardev socket,id=id,path=path[,server][,nowait][,telnet] (unix)\n"
+ " [,server][,nowait][,telnet][,mux=on|off] (tcp)\n"
+ "-chardev socket,id=id,path=path[,server][,nowait][,telnet],[mux=on|off] (unix)\n"
"-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
- " [,localport=localport][,ipv4][,ipv6]\n"
- "-chardev msmouse,id=id\n"
+ " [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n"
+ "-chardev msmouse,id=id[,mux=on|off]\n"
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
- "-chardev file,id=id,path=path\n"
- "-chardev pipe,id=id,path=path\n"
+ " [,mux=on|off]\n"
+ "-chardev file,id=id,path=path[,mux=on|off]\n"
+ "-chardev pipe,id=id,path=path[,mux=on|off]\n"
#ifdef _WIN32
- "-chardev console,id=id\n"
- "-chardev serial,id=id,path=path\n"
+ "-chardev console,id=id[,mux=on|off]\n"
+ "-chardev serial,id=id,path=path[,mux=on|off]\n"
#else
- "-chardev pty,id=id\n"
- "-chardev stdio,id=id\n"
+ "-chardev pty,id=id[,mux=on|off]\n"
+ "-chardev stdio,id=id[,mux=on|off]\n"
#endif
#ifdef CONFIG_BRLAPI
- "-chardev braille,id=id\n"
+ "-chardev braille,id=id[,mux=on|off]\n"
#endif
#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
- "-chardev tty,id=id,path=path\n"
+ "-chardev tty,id=id,path=path[,mux=on|off]\n"
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
- "-chardev parport,id=id,path=path\n"
+ "-chardev parport,id=id,path=path[,mux=on|off]\n"
#endif
, QEMU_ARCH_ALL
)
@@ -1210,7 +1211,7 @@ STEXI
The general form of a character device option is:
@table @option
-@item -chardev @var{backend} ,id=@var{id} [,@var{options}]
+@item -chardev @var{backend} ,id=@var{id} [,mux=on|off] [,@var{options}]
@findex -chardev
Backend is one of:
@option{null},
@@ -1232,6 +1233,10 @@ The specific backend will determine the applicable options.
All devices must have an id, which can be any string up to 127 characters long.
It is used to uniquely identify this device in other command line directives.
+A character device may be used in multiplexing mode by multiple front-ends.
+The key sequence of @key{Control-a} and @key{c} will rotate the input focus
+between attached front-ends. Specify @option{mux=on} to enable this mode.
+
Options to each backend are described below.
@item -chardev null ,id=@var{id}
diff --git a/qerror.c b/qerror.c
index 8d885cd..034c7de 100644
--- a/qerror.c
+++ b/qerror.c
@@ -170,7 +170,11 @@ static const QErrorStringTable qerror_table[] = {
},
{
.error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
- .desc = "Bad QMP input object",
+ .desc = "Expected '%(expected)' in QMP input",
+ },
+ {
+ .error_fmt = QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+ .desc = "QMP input object member '%(member)' expects '%(expected)'",
},
{
.error_fmt = QERR_SET_PASSWD_FAILED,
diff --git a/qerror.h b/qerror.h
index bae08c0..c98c61a 100644
--- a/qerror.h
+++ b/qerror.h
@@ -145,6 +145,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_QMP_BAD_INPUT_OBJECT \
"{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
+#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \
+ "{ 'class': 'QMPBadInputObjectMember', 'data': { 'member': %s, 'expected': %s } }"
+
#define QERR_SET_PASSWD_FAILED \
"{ 'class': 'SetPasswdFailed', 'data': {} }"
diff --git a/sysemu.h b/sysemu.h
index d0effa0..fa921df 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -45,9 +45,11 @@ void cpu_disable_ticks(void);
void qemu_system_reset_request(void);
void qemu_system_shutdown_request(void);
void qemu_system_powerdown_request(void);
+void qemu_system_exit_request(void);
int qemu_shutdown_requested(void);
int qemu_reset_requested(void);
int qemu_powerdown_requested(void);
+int qemu_exit_requested(void);
extern qemu_irq qemu_system_powerdown;
void qemu_system_reset(void);
diff --git a/vl.c b/vl.c
index a5a0f41..a485c58 100644
--- a/vl.c
+++ b/vl.c
@@ -1697,6 +1697,7 @@ static int shutdown_requested;
static int powerdown_requested;
int debug_requested;
int vmstop_requested;
+static int exit_requested;
int qemu_shutdown_requested(void)
{
@@ -1719,6 +1720,12 @@ int qemu_powerdown_requested(void)
return r;
}
+int qemu_exit_requested(void)
+{
+ /* just return it, we'll exit() anyway */
+ return exit_requested;
+}
+
static int qemu_debug_requested(void)
{
int r = debug_requested;
@@ -1789,6 +1796,12 @@ void qemu_system_powerdown_request(void)
qemu_notify_event();
}
+void qemu_system_exit_request(void)
+{
+ exit_requested = 1;
+ qemu_notify_event();
+}
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -1925,6 +1938,8 @@ static int vm_can_run(void)
return 0;
if (debug_requested)
return 0;
+ if (exit_requested)
+ return 0;
return 1;
}
@@ -1977,6 +1992,9 @@ static void main_loop(void)
if ((r = qemu_vmstop_requested())) {
vm_stop(r);
}
+ if (qemu_exit_requested()) {
+ exit(0);
+ }
}
pause_all_vcpus();
}
@@ -2330,11 +2348,9 @@ static void monitor_parse(const char *optarg, const char *mode)
if (strstart(optarg, "chardev:", &p)) {
snprintf(label, sizeof(label), "%s", p);
} else {
- if (monitor_device_index) {
- snprintf(label, sizeof(label), "monitor%d",
- monitor_device_index);
- } else {
- snprintf(label, sizeof(label), "monitor");
+ snprintf(label, sizeof(label), "compat_monitor%d",
+ monitor_device_index);
+ if (monitor_device_index == 0) {
def = 1;
}
opts = qemu_chr_parse_compat(label, optarg);
@@ -3602,6 +3618,10 @@ int main(int argc, char **argv, char **envp)
}
}
+ if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0) {
+ exit(1);
+ }
+
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
exit(1);
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
@@ -3714,9 +3734,6 @@ int main(int argc, char **argv, char **envp)
text_consoles_set_display(ds);
- if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
- exit(1);
-
if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
gdbstub_dev);