diff --git a/repos/base/run/registry.run b/repos/base/run/registry.run
new file mode 100644
index 0000000000..67a1d8f939
--- /dev/null
+++ b/repos/base/run/registry.run
@@ -0,0 +1,27 @@
+build "core init test/registry"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image "core ld.lib.so init test-registry"
+
+append qemu_args "-nographic "
+
+run_genode_until ".*child \"test-registry\" exited with exit value 0.*\n" 20
diff --git a/repos/base/src/lib/base/registry.cc b/repos/base/src/lib/base/registry.cc
index 07ef5a2b44..3ac68c64bf 100644
--- a/repos/base/src/lib/base/registry.cc
+++ b/repos/base/src/lib/base/registry.cc
@@ -134,7 +134,21 @@ void Registry_base::_for_each(Untyped_functor &functor)
try { functor.call(e->_obj); }
/* propagate exceptions while keeping registry consistent */
- catch (...) { at = _processed(notify, processed, *e, at); throw; }
+ catch (...) {
+
+ /* handle current element */
+ at = _processed(notify, processed, *e, at);
+
+ /* handle the remaining elements without invoking the functor */
+ while (Element *e = _elements.first()) {
+ _elements.remove(e);
+ at = _processed(notify, processed, *e, at);
+ };
+ _elements = processed;
+
+ /* propagate exception to caller */
+ throw;
+ }
at = _processed(notify, processed, *e, at);
}
diff --git a/repos/base/src/test/registry/main.cc b/repos/base/src/test/registry/main.cc
new file mode 100644
index 0000000000..502637bcea
--- /dev/null
+++ b/repos/base/src/test/registry/main.cc
@@ -0,0 +1,79 @@
+/*
+ * \brief Test for 'Registry' data structure
+ * \author Norman Feske
+ * \date 2018-08-21
+ */
+
+/*
+ * Copyright (C) 2018 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+
+
+/*
+ * Check that an exception that occurs during the iteration over
+ * registry items does not affect the registry content.
+ */
+static void test_exception_during_for_each()
+{
+ using namespace Genode;
+
+ struct Item : Interface
+ {
+ typedef String<10> Name;
+ Name const name;
+
+ Item(Name const &name) : name(name) { }
+
+ class Invalid : Exception { };
+
+ void visit()
+ {
+ if (name == "second")
+ throw Invalid();
+ }
+ };
+
+ Registry > items { };
+
+ Registered- first (items, "first");
+ Registered
- second(items, "second");
+ Registered
- third (items, "third");
+
+ auto num_items = [&] () {
+ unsigned cnt = 0;
+ items.for_each([&] (Item &) { cnt++; });
+ return cnt;
+ };
+
+ unsigned const num_items_before_exception = num_items();
+
+ try {
+ items.for_each([&] (Item &item) {
+ /* second item throws an exception */
+ item.visit();
+ });
+ }
+ catch (Item::Invalid) { log("exception occurred (expected)"); };
+
+ unsigned const num_items_after_exception = num_items();
+
+ struct Failed : Exception { };
+ if (num_items_before_exception != num_items_after_exception)
+ throw Failed();
+}
+
+
+void Component::construct(Genode::Env &env)
+{
+ test_exception_during_for_each();
+
+ env.parent().exit(0);
+}
diff --git a/repos/base/src/test/registry/target.mk b/repos/base/src/test/registry/target.mk
new file mode 100644
index 0000000000..7eb11de97e
--- /dev/null
+++ b/repos/base/src/test/registry/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-registry
+SRC_CC = main.cc
+LIBS += base
diff --git a/tool/autopilot.list b/tool/autopilot.list
index c84f1b52f9..4a603e6be3 100644
--- a/tool/autopilot.list
+++ b/tool/autopilot.list
@@ -71,6 +71,7 @@ pthread
python
ram_fs_chunk
reconstructible
+registry
report_rom
resource_request
resource_yield