f5de326
diff -Nur audacious-3.6.2-orig/src/audacious/main.cc audacious-3.6.2/src/audacious/main.cc
f5de326
--- audacious-3.6.2-orig/src/audacious/main.cc	2015-05-31 00:27:01.000000000 +0200
f5de326
+++ audacious-3.6.2/src/audacious/main.cc	2015-11-22 12:24:15.858308588 +0100
f5de326
@@ -49,6 +49,7 @@
f5de326
     int qt;
f5de326
 } options;
f5de326
 
f5de326
+static bool initted = false;
f5de326
 static Index<PlaylistAddItem> filenames;
f5de326
 
f5de326
 static const struct {
f5de326
@@ -300,6 +301,16 @@
f5de326
 
f5de326
 static void main_cleanup (void)
f5de326
 {
f5de326
+    if (initted)
f5de326
+    {
f5de326
+        /* Somebody was naughty and called exit() instead of aud_quit().
f5de326
+         * aud_cleanup() has not been called yet, so there's no point in running
f5de326
+         * leak checks.  Note that it's not safe to call aud_cleanup() from the
f5de326
+         * exit handler, since we don't know what context we're in (we could be
f5de326
+         * deep inside the call tree of some plugin, for example). */
f5de326
+        AUDWARN ("exit() called unexpectedly; skipping normal cleanup.\n");
f5de326
+        return;
f5de326
+    }
f5de326
     filenames.clear ();
f5de326
     aud_cleanup_paths ();
f5de326
     aud_leak_check ();
f5de326
@@ -356,6 +367,7 @@
f5de326
     signals_init_two ();
f5de326
 #endif
f5de326
 
f5de326
+    initted = true;
f5de326
     aud_init ();
f5de326
 
f5de326
     do_commands ();
f5de326
@@ -379,6 +391,7 @@
f5de326
 #endif
f5de326
 
f5de326
     aud_cleanup ();
f5de326
+    initted = false;
f5de326
 
f5de326
     return EXIT_SUCCESS;
f5de326
 }
f5de326
diff -Nur audacious-3.6.2-orig/src/libaudcore/multihash.h audacious-3.6.2/src/libaudcore/multihash.h
f5de326
--- audacious-3.6.2-orig/src/libaudcore/multihash.h	2015-05-31 00:27:01.000000000 +0200
f5de326
+++ audacious-3.6.2/src/libaudcore/multihash.h	2015-11-22 12:22:45.550171540 +0100
f5de326
@@ -54,9 +54,12 @@
f5de326
         size (0),
f5de326
         used (0) {}
f5de326
 
f5de326
-    ~HashBase ()
f5de326
-        { delete[] buckets; }
f5de326
-
f5de326
+    void clear ()  // use as destructor
f5de326
+    {
f5de326
+        delete[] buckets;
f5de326
+        * this = HashBase ();
f5de326
+    }
f5de326
+ 
f5de326
     int n_items () const
f5de326
         { return used; }
f5de326
 
f5de326
@@ -112,6 +115,11 @@
f5de326
         locks (),
f5de326
         channels () {}
f5de326
 
f5de326
+    /* There is no destructor.  In some instances, such as the string pool, it
f5de326
+     * is never safe to destroy the hash table, since it can be referenced from
f5de326
+     * the destructors of other static objects.  It is left to the operating
f5de326
+     * system to reclaim the memory used by the hash table upon process exit. */
f5de326
+
f5de326
     /* All-purpose lookup function.  The caller passes in the data to be looked
f5de326
      * up along with its hash value.  The two callbacks are optional.  <add> is
f5de326
      * called if no matching node is found, and may return a new node to add to
f5de326
@@ -187,8 +195,11 @@
f5de326
     }
f5de326
 
f5de326
     void clear ()
f5de326
-        { HashBase::iterate (remove_cb, nullptr); }
f5de326
-
f5de326
+    {
f5de326
+        HashBase::iterate (remove_cb, nullptr);
f5de326
+        HashBase::clear ();
f5de326
+    }
f5de326
+    
f5de326
 private:
f5de326
     struct Node : public HashBase::Node
f5de326
     {