Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2016-08-08' into staging

Monitor patches for 2016-08-08

# gpg: Signature made Mon 08 Aug 2016 13:24:42 BST
# gpg:                using RSA key 0x3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-monitor-2016-08-08:
  audio: clean up before monitor clean up
  monitor: fix crash when leaving qemu with spice audio

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/audio/audio.c b/audio/audio.c
index 9d4dcc7..c845a44 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1739,13 +1739,21 @@
     audio_reset_timer (s);
 }
 
-static void audio_atexit (void)
+static bool is_cleaning_up;
+
+bool audio_is_cleaning_up(void)
+{
+    return is_cleaning_up;
+}
+
+void audio_cleanup(void)
 {
     AudioState *s = &glob_audio_state;
-    HWVoiceOut *hwo = NULL;
-    HWVoiceIn *hwi = NULL;
+    HWVoiceOut *hwo, *hwon;
+    HWVoiceIn *hwi, *hwin;
 
-    while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
+    is_cleaning_up = true;
+    QLIST_FOREACH_SAFE(hwo, &glob_audio_state.hw_head_out, entries, hwon) {
         SWVoiceCap *sc;
 
         if (hwo->enabled) {
@@ -1761,17 +1769,20 @@
                 cb->ops.destroy (cb->opaque);
             }
         }
+        QLIST_REMOVE(hwo, entries);
     }
 
-    while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
+    QLIST_FOREACH_SAFE(hwi, &glob_audio_state.hw_head_in, entries, hwin) {
         if (hwi->enabled) {
             hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
         }
         hwi->pcm_ops->fini_in (hwi);
+        QLIST_REMOVE(hwi, entries);
     }
 
     if (s->drv) {
         s->drv->fini (s->drv_opaque);
+        s->drv = NULL;
     }
 }
 
@@ -1799,7 +1810,7 @@
     QLIST_INIT (&s->hw_head_out);
     QLIST_INIT (&s->hw_head_in);
     QLIST_INIT (&s->cap_head);
-    atexit (audio_atexit);
+    atexit(audio_cleanup);
 
     s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
 
@@ -1966,8 +1977,7 @@
         QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
         QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
 
-        hw = NULL;
-        while ((hw = audio_pcm_hw_find_any_out (hw))) {
+        QLIST_FOREACH(hw, &glob_audio_state.hw_head_out, entries) {
             audio_attach_capture (hw);
         }
         return cap;
diff --git a/audio/audio.h b/audio/audio.h
index 11e56c9..c3c5198 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -163,4 +163,7 @@
 int wav_start_capture (CaptureState *s, const char *path, int freq,
                        int bits, int nchannels);
 
+bool audio_is_cleaning_up(void);
+void audio_cleanup(void);
+
 #endif /* QEMU_AUDIO_H */
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index d4ad224..c751420 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -36,8 +36,6 @@
 #define MAC_OS_X_VERSION_10_6 1060
 #endif
 
-static int isAtexit;
-
 typedef struct {
     int buffer_frames;
     int nbuffers;
@@ -378,11 +376,6 @@
     return result;
 }
 
-static void coreaudio_atexit (void)
-{
-    isAtexit = 1;
-}
-
 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
 {
     int err;
@@ -630,7 +623,7 @@
     int err;
     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
 
-    if (!isAtexit) {
+    if (!audio_is_cleaning_up()) {
         /* stop playback */
         if (isPlaying(core->outputDeviceID)) {
             status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
@@ -673,7 +666,7 @@
 
     case VOICE_DISABLE:
         /* stop playback */
-        if (!isAtexit) {
+        if (!audio_is_cleaning_up()) {
             if (isPlaying(core->outputDeviceID)) {
                 status = AudioDeviceStop(core->outputDeviceID,
                                          core->ioprocid);
@@ -697,7 +690,6 @@
     CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
     *conf = glob_conf;
 
-    atexit(coreaudio_atexit);
     return conf;
 }
 
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index c5c9ea2..a714d8e 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -17,6 +17,7 @@
 bool monitor_cur_is_qmp(void);
 
 void monitor_init(CharDriverState *chr, int flags);
+void monitor_cleanup(void);
 
 int monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
diff --git a/monitor.c b/monitor.c
index 5d68a5d..5c00373 100644
--- a/monitor.c
+++ b/monitor.c
@@ -635,6 +635,13 @@
 
 static void monitor_data_destroy(Monitor *mon)
 {
+    if (mon->chr) {
+        qemu_chr_add_handlers(mon->chr, NULL, NULL, NULL, NULL);
+    }
+    if (monitor_is_qmp(mon)) {
+        json_message_parser_destroy(&mon->qmp.parser);
+    }
+    g_free(mon->rs);
     QDECREF(mon->outbuf);
     qemu_mutex_destroy(&mon->out_lock);
 }
@@ -4196,6 +4203,19 @@
     qemu_mutex_unlock(&monitor_lock);
 }
 
+void monitor_cleanup(void)
+{
+    Monitor *mon, *next;
+
+    qemu_mutex_lock(&monitor_lock);
+    QLIST_FOREACH_SAFE(mon, &mon_list, entry, next) {
+        QLIST_REMOVE(mon, entry);
+        monitor_data_destroy(mon);
+        g_free(mon);
+    }
+    qemu_mutex_unlock(&monitor_lock);
+}
+
 static void bdrv_password_cb(void *opaque, const char *password,
                              void *readline_opaque)
 {
diff --git a/vl.c b/vl.c
index e7c2c62..c4eeaff 100644
--- a/vl.c
+++ b/vl.c
@@ -4612,6 +4612,8 @@
 
     /* vhost-user must be cleaned up before chardevs.  */
     net_cleanup();
+    audio_cleanup();
+    monitor_cleanup();
     qemu_chr_cleanup();
 
     return 0;