If a CPU selected with the "cpu" command is hot-unplugged then "info cpus" causes QEMU to exit:
(qemu) device_del cpu1 (qemu) info cpus qemu:qemu_cpu_kick_thread: No such process This happens because "cpu" stores the pointer to the selected CPU into the monitor structure. When the CPU is hot-unplugged, we end up with a dangling pointer. The "info cpus" command then does: hmp_info_cpus() monitor_get_cpu_index() mon_get_cpu() cpu_synchronize_state() <--- called with dangling pointer This could cause a QEMU crash as well. This patch switches the monitor to use object_ref() to ensure the CPU object doesn't vanish unexpectedly. The reference is dropped either when "cpu" is used to switch to another CPU, or when the selected CPU is unrealized and cpu_list_remove() sets its cpu_index back to UNASSIGNED_CPU_INDEX. Signed-off-by: Greg Kurz <gr...@kaod.org> --- monitor.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/monitor.c b/monitor.c index fe0d1bdbb461..1c0b9a2c3ad3 100644 --- a/monitor.c +++ b/monitor.c @@ -579,6 +579,9 @@ static void monitor_data_init(Monitor *mon) static void monitor_data_destroy(Monitor *mon) { + if (mon->mon_cpu) { + object_unref((Object *) mon->mon_cpu); + } qemu_chr_fe_deinit(&mon->chr, false); if (monitor_is_qmp(mon)) { json_message_parser_destroy(&mon->qmp.parser); @@ -1047,12 +1050,21 @@ int monitor_set_cpu(int cpu_index) if (cpu == NULL) { return -1; } + if (cur_mon->mon_cpu) { + object_unref((Object *) cur_mon->mon_cpu); + } cur_mon->mon_cpu = cpu; + object_ref((Object *) cpu); return 0; } CPUState *mon_get_cpu(void) { + if (cur_mon->mon_cpu && + cur_mon->mon_cpu->cpu_index == UNASSIGNED_CPU_INDEX) { + object_unref((Object *) cur_mon->mon_cpu); + cur_mon->mon_cpu = NULL; + } if (!cur_mon->mon_cpu) { if (!first_cpu) { return NULL;