2009-03-06 07:01:23 +08:00
|
|
|
#ifndef MONITOR_H
|
|
|
|
#define MONITOR_H
|
|
|
|
|
|
|
|
#include "qemu-common.h"
|
2012-12-18 01:19:44 +08:00
|
|
|
#include "block/block.h"
|
2018-02-27 07:13:27 +08:00
|
|
|
#include "qapi/qapi-types-misc.h"
|
2013-11-14 18:54:15 +08:00
|
|
|
#include "qemu/readline.h"
|
2009-03-06 07:01:23 +08:00
|
|
|
|
monitor: Fix unsafe sharing of @cur_mon among threads
@cur_mon is null unless the main thread is running monitor code, either
HMP code within monitor_read(), or QMP code within
monitor_qmp_dispatch().
Use of @cur_mon outside the main thread is therefore unsafe.
Most of its uses are in monitor command handlers. These run in the main
thread.
However, there are also uses hiding elsewhere, such as in
error_vprintf(), and thus error_report(), making these functions unsafe
outside the main thread. No such unsafe uses are known at this time.
Regardless, this is an unnecessary trap. It's an ancient trap, though.
More recently, commit cf869d53172 "qmp: support out-of-band (oob)
execution" spiced things up: the monitor I/O thread assigns to @cur_mon
when executing commands out-of-band. Having two threads save, set and
restore @cur_mon without synchronization is definitely unsafe. We can
end up with @cur_mon null while the main thread runs monitor code, or
non-null while it runs non-monitor code.
We could fix this by making the I/O thread not mess with @cur_mon, but
that would leave the trap armed and ready.
Instead, make @cur_mon thread-local. It's now reliably null unless the
thread is running monitor code.
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[peterx: update subject and commit message written by Markus]
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20180720033451.32710-1-peterx@redhat.com>
2018-07-20 11:34:51 +08:00
|
|
|
extern __thread Monitor *cur_mon;
|
2009-03-06 07:01:23 +08:00
|
|
|
|
2009-03-06 07:01:42 +08:00
|
|
|
/* flags for monitor_init */
|
2016-10-12 01:41:21 +08:00
|
|
|
/* 0x01 unused */
|
2009-03-06 07:01:51 +08:00
|
|
|
#define MONITOR_USE_READLINE 0x02
|
2009-11-27 08:58:51 +08:00
|
|
|
#define MONITOR_USE_CONTROL 0x04
|
2010-06-07 22:42:31 +08:00
|
|
|
#define MONITOR_USE_PRETTY 0x08
|
2018-03-26 14:38:56 +08:00
|
|
|
#define MONITOR_USE_OOB 0x10
|
2009-03-06 07:01:42 +08:00
|
|
|
|
2015-03-07 03:01:05 +08:00
|
|
|
bool monitor_cur_is_qmp(void);
|
2010-02-12 00:05:43 +08:00
|
|
|
|
2018-03-09 16:59:50 +08:00
|
|
|
void monitor_init_globals(void);
|
2016-12-07 21:20:22 +08:00
|
|
|
void monitor_init(Chardev *chr, int flags);
|
monitor: fix crash when leaving qemu with spice audio
Since aa5cb7f5e, the chardevs are being cleaned up when leaving
qemu. However, the monitor has still references to them, which may
lead to crashes when running atexit() and trying to send monitor
events:
#0 0x00007fffdb18f6f5 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007fffdb1912fa in __GI_abort () at abort.c:89
#2 0x0000555555c263e7 in error_exit (err=22, msg=0x555555d47980 <__func__.13537> "qemu_mutex_lock") at util/qemu-thread-posix.c:39
#3 0x0000555555c26488 in qemu_mutex_lock (mutex=0x5555567a2420) at util/qemu-thread-posix.c:66
#4 0x00005555558c52db in qemu_chr_fe_write (s=0x5555567a2420, buf=0x55555740dc40 "{\"timestamp\": {\"seconds\": 1470041716, \"microseconds\": 989699}, \"event\": \"SPICE_DISCONNECTED\", \"data\": {\"server\": {\"port\": \"5900\", \"family\": \"ipv4\", \"host\": \"127.0.0.1\"}, \"client\": {\"port\": \"40272\", \"f"..., len=240) at qemu-char.c:280
#5 0x0000555555787cad in monitor_flush_locked (mon=0x5555567bd9e0) at /home/elmarco/src/qemu/monitor.c:311
#6 0x0000555555787e46 in monitor_puts (mon=0x5555567bd9e0, str=0x5555567a44ef "") at /home/elmarco/src/qemu/monitor.c:353
#7 0x00005555557880fe in monitor_json_emitter (mon=0x5555567bd9e0, data=0x5555567c73a0) at /home/elmarco/src/qemu/monitor.c:401
#8 0x00005555557882d2 in monitor_qapi_event_emit (event=QAPI_EVENT_SPICE_DISCONNECTED, qdict=0x5555567c73a0) at /home/elmarco/src/qemu/monitor.c:472
#9 0x000055555578838f in monitor_qapi_event_queue (event=QAPI_EVENT_SPICE_DISCONNECTED, qdict=0x5555567c73a0, errp=0x7fffffffca88) at /home/elmarco/src/qemu/monitor.c:497
#10 0x0000555555c15541 in qapi_event_send_spice_disconnected (server=0x5555571139d0, client=0x5555570d0db0, errp=0x5555566c0428 <error_abort>) at qapi-event.c:1038
#11 0x0000555555b11bc6 in channel_event (event=3, info=0x5555570d6c00) at ui/spice-core.c:248
#12 0x00007fffdcc9983a in adapter_channel_event (event=3, info=0x5555570d6c00) at reds.c:120
#13 0x00007fffdcc99a25 in reds_handle_channel_event (reds=0x5555567a9d60, event=3, info=0x5555570d6c00) at reds.c:324
#14 0x00007fffdcc7d4c4 in main_dispatcher_self_handle_channel_event (self=0x5555567b28b0, event=3, info=0x5555570d6c00) at main-dispatcher.c:175
#15 0x00007fffdcc7d5b1 in main_dispatcher_channel_event (self=0x5555567b28b0, event=3, info=0x5555570d6c00) at main-dispatcher.c:194
#16 0x00007fffdcca7674 in reds_stream_push_channel_event (s=0x5555570d9910, event=3) at reds-stream.c:354
#17 0x00007fffdcca749b in reds_stream_free (s=0x5555570d9910) at reds-stream.c:323
#18 0x00007fffdccb5dad in snd_disconnect_channel (channel=0x5555576a89a0) at sound.c:229
#19 0x00007fffdccb9e57 in snd_detach_common (worker=0x555557739720) at sound.c:1589
#20 0x00007fffdccb9f0e in snd_detach_playback (sin=0x5555569fe3f8) at sound.c:1602
#21 0x00007fffdcca3373 in spice_server_remove_interface (sin=0x5555569fe3f8) at reds.c:3387
#22 0x00005555558ff6e2 in line_out_fini (hw=0x5555569fe370) at audio/spiceaudio.c:152
#23 0x00005555558f909e in audio_atexit () at audio/audio.c:1754
#24 0x00007fffdb1941e8 in __run_exit_handlers (status=0, listp=0x7fffdb5175d8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:82
#25 0x00007fffdb194235 in __GI_exit (status=<optimized out>) at exit.c:104
#26 0x00007fffdb17b738 in __libc_start_main (main=0x5555558d7874 <main>, argc=67, argv=0x7fffffffcf48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffcf38) at ../csu/libc-start.c:323
Add a monitor_cleanup() functions to remove all the monitors before
cleaning up the chardev. Note that we are "losing" some events that
used to be sent during atexit().
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20160801112343.29082-2-marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-08-01 19:23:42 +08:00
|
|
|
void monitor_cleanup(void);
|
2009-03-06 07:01:23 +08:00
|
|
|
|
2009-03-06 07:01:51 +08:00
|
|
|
int monitor_suspend(Monitor *mon);
|
2009-03-06 07:01:23 +08:00
|
|
|
void monitor_resume(Monitor *mon);
|
|
|
|
|
2012-09-20 22:50:32 +08:00
|
|
|
int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
|
2015-02-09 21:03:19 +08:00
|
|
|
int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp);
|
2009-07-22 16:11:41 +08:00
|
|
|
|
2010-09-24 03:28:05 +08:00
|
|
|
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
|
|
|
GCC_FMT_ATTR(2, 0);
|
2010-09-24 03:28:03 +08:00
|
|
|
void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
2015-09-22 21:18:17 +08:00
|
|
|
int monitor_fprintf(FILE *stream, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
2009-03-06 07:01:23 +08:00
|
|
|
void monitor_flush(Monitor *mon);
|
2011-10-07 01:02:57 +08:00
|
|
|
int monitor_set_cpu(int cpu_index);
|
2011-10-24 20:53:44 +08:00
|
|
|
int monitor_get_cpu_index(void);
|
2009-03-06 07:01:23 +08:00
|
|
|
|
2011-09-03 01:34:50 +08:00
|
|
|
void monitor_read_command(Monitor *mon, int show_prompt);
|
|
|
|
int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
|
|
|
|
void *opaque);
|
2010-02-17 17:52:26 +08:00
|
|
|
|
2012-10-19 03:19:32 +08:00
|
|
|
AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
|
|
|
|
bool has_opaque, const char *opaque,
|
|
|
|
Error **errp);
|
2012-08-15 04:43:47 +08:00
|
|
|
int monitor_fdset_get_fd(int64_t fdset_id, int flags);
|
|
|
|
int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd);
|
2014-08-17 17:45:17 +08:00
|
|
|
void monitor_fdset_dup_fd_remove(int dup_fd);
|
2012-08-15 04:43:47 +08:00
|
|
|
int monitor_fdset_dup_fd_find(int dup_fd);
|
|
|
|
|
2016-06-29 21:29:06 +08:00
|
|
|
#endif /* MONITOR_H */
|