diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index cd87d9484872fc701736182f21abee539425e692..879fd617aebb7e157de6d67bbdf374f339c36b81 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,8 @@
+2013-07-22  Jason Merrill  <jason@redhat.com>
+
+	PR libstdc++/57914
+	* libsupc++/atexit_thread.cc (run): Delete cleanup elts.
+
 2013-07-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/57920
diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc
index 3b33df233e817184fb14b3804e94480b595b7fd9..11f1dbdeac4a4655cac5f3c57f74695b38e7dc9d 100644
--- a/libstdc++-v3/libsupc++/atexit_thread.cc
+++ b/libstdc++-v3/libsupc++/atexit_thread.cc
@@ -58,8 +58,13 @@ namespace {
   void run (void *p)
   {
     elt *e = static_cast<elt*>(p);
-    for (; e; e = e->next)
-      e->destructor (e->object);
+    while (e)
+      {
+	elt *old_e = e;
+	e->destructor (e->object);
+	e = e->next;
+	delete (old_e);
+      }
   }
 
   // Run the stack of cleanups for the current thread.
@@ -67,9 +72,15 @@ namespace {
   {
     void *e;
     if (__gthread_active_p ())
-      e = __gthread_getspecific (key);
+      {
+	e = __gthread_getspecific (key);
+	__gthread_setspecific (key, NULL);
+      }
     else
-      e = single_thread;
+      {
+	e = single_thread;
+	single_thread = NULL;
+      }
     run (e);
   }