[gold][patch] Fix gold plugins so cleanup handler is not called repeatedly

Cary Coutant ccoutant@google.com
Wed Oct 28 00:53:00 GMT 2009


The attached patch fixes a problem that can occur when a plugin's
cleanup handler issues a fatal error through the linker's message API.
This moves the cleanup_done_ flag into each plugin and sets each
plugin's cleanup_done_ flag just before invoking the cleanup handler.

OK?

-cary

	* plugin.h (Plugin::Plugin): Initialize cleanup_done_.
	(Plugin::cleanup_done_): New member.
	(Plugin_manager::Plugin_manager): Remove cleanup_done_.
	(Plugin_manager::cleanup_done_): Remove.
	* plugin.cc (Plugin::cleanup): Test and set cleanup_done_.
	(Plugin_manager::cleanup): Remove use of cleanup_done_.
-------------- next part --------------
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.22
diff -u -p -r1.22 plugin.cc
--- plugin.cc	12 Oct 2009 06:02:06 -0000	1.22
+++ plugin.cc	28 Oct 2009 00:50:05 -0000
@@ -238,8 +238,14 @@ Plugin::all_symbols_read()
 inline void
 Plugin::cleanup()
 {
-  if (this->cleanup_handler_ != NULL)
-    (*this->cleanup_handler_)();
+  if (this->cleanup_handler_ != NULL && !this->cleanup_done_)
+    {
+      // Set this flag before calling to prevent a recursive plunge
+      // in the event that a plugin's cleanup handler issues a
+      // fatal error.
+      this->cleanup_done_ = true;
+      (*this->cleanup_handler_)();
+    }
 }
 
 // Plugin_manager methods.
@@ -350,13 +356,10 @@ Plugin_manager::layout_deferred_objects(
 void
 Plugin_manager::cleanup()
 {
-  if (this->cleanup_done_)
-    return;
   for (this->current_ = this->plugins_.begin();
        this->current_ != this->plugins_.end();
        ++this->current_)
     (*this->current_)->cleanup();
-  this->cleanup_done_ = true;
 }
 
 // Make a new Pluginobj object.  This is called when the plugin calls
Index: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.8
diff -u -p -r1.8 plugin.h
--- plugin.h	6 Oct 2009 20:15:09 -0000	1.8
+++ plugin.h	28 Oct 2009 00:50:05 -0000
@@ -54,7 +54,8 @@ class Plugin
       args_(),
       claim_file_handler_(NULL),
       all_symbols_read_handler_(NULL),
-      cleanup_handler_(NULL)      
+      cleanup_handler_(NULL),
+      cleanup_done_(false)
   { }
 
   ~Plugin()
@@ -112,6 +113,8 @@ class Plugin
   ld_plugin_claim_file_handler claim_file_handler_;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
   ld_plugin_cleanup_handler cleanup_handler_;
+  // TRUE if the cleanup handlers have been called.
+  bool cleanup_done_;
 };
 
 // A manager class for plugins.
@@ -121,7 +124,7 @@ class Plugin_manager
  public:
   Plugin_manager(const General_options& options)
     : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
-      plugin_input_file_(), in_replacement_phase_(false), cleanup_done_(false),
+      plugin_input_file_(), in_replacement_phase_(false),
       options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
       symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
       this_blocker_(NULL)
@@ -263,9 +266,6 @@ class Plugin_manager
   // placeholder symbols from the Pluginobj objects.
   bool in_replacement_phase_;
 
-  // TRUE if the cleanup handlers have been called.
-  bool cleanup_done_;
-
   const General_options& options_;
   Workqueue* workqueue_;
   Task* task_;


More information about the Binutils mailing list