Merge "Add support for std::set_new_handler in Gabi++"
diff --git a/sources/cxx-stl/gabi++/include/new b/sources/cxx-stl/gabi++/include/new
index 7687c9b..d66fef7 100644
--- a/sources/cxx-stl/gabi++/include/new
+++ b/sources/cxx-stl/gabi++/include/new
@@ -48,6 +48,9 @@
   virtual const char* what() const throw();
 };
 
+typedef void (*new_handler)();
+new_handler set_new_handler(new_handler) throw();
+
 }
 
 void* operator new(std::size_t size) throw(std::bad_alloc);
diff --git a/sources/cxx-stl/gabi++/src/new.cc b/sources/cxx-stl/gabi++/src/new.cc
index 8148556..f65a291 100644
--- a/sources/cxx-stl/gabi++/src/new.cc
+++ b/sources/cxx-stl/gabi++/src/new.cc
@@ -29,6 +29,11 @@
 #include <stdlib.h>
 #include <new>
 
+using std::new_handler;
+namespace {
+  new_handler cur_handler;
+}
+
 namespace std {
 
 #if !defined(GABIXX_LIBCXX)
@@ -45,21 +50,37 @@
     return "std::bad_alloc";
   }
 
+  new_handler set_new_handler(new_handler next_handler) throw() {
+    new_handler old_handler = cur_handler;
+    cur_handler = next_handler;
+    return old_handler;
+  }
+
 } // namespace std
 
 __attribute__ ((weak))
 void* operator new(std::size_t size) throw(std::bad_alloc) {
-  void* space = ::operator new(size, std::nothrow_t());
-  if (space) {
-    return space;
-  } else {
-    throw std::bad_alloc();
-  }
+  void* space;
+  do {
+    space = malloc(size);
+    if (space) {
+      return space;
+    }
+    new_handler handler = cur_handler;
+    if (handler == NULL) {
+      throw std::bad_alloc();
+    }
+    handler();
+  } while (space == 0);
 }
 
 __attribute__ ((weak))
 void* operator new(std::size_t size, const std::nothrow_t& no) throw() {
-  return malloc(size);
+  try {
+    ::operator new(size);
+  } catch (const std::bad_alloc&) {
+    return 0;
+  }
 }
 
 __attribute__ ((weak))