* descriptors.cc: Include "options.h".
authorIan Lance Taylor <ian@airs.com>
Tue, 17 Mar 2009 17:09:44 +0000 (17:09 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 17 Mar 2009 17:09:44 +0000 (17:09 +0000)
(FD_CLOEXEC, O_CLOEXEC): Define if not defined.
(Descriptors::open): Always use O_CLOEXEC when opening a new
descriptor.  If we have a plugin, and O_CLOEXEC was not defined,
then set FD_CLOEXEC.

gold/ChangeLog
gold/descriptors.cc

index 7af69c498558f8d66ec58a036d18cac559f1cba8..9425ea6e60e17f2c03ad2b042e39b2c2b7ad2329 100644 (file)
@@ -1,5 +1,11 @@
 2009-03-17  Ian Lance Taylor  <iant@google.com>
 
+       * descriptors.cc: Include "options.h".
+       (FD_CLOEXEC, O_CLOEXEC): Define if not defined.
+       (Descriptors::open): Always use O_CLOEXEC when opening a new
+       descriptor.  If we have a plugin, and O_CLOEXEC was not defined,
+       then set FD_CLOEXEC.
+
        * sparc.cc (class Target_sparc): Add has_got_section.
        (Target_sparc::Scan::global): If we see _GLOBAL_OFFSET_TABLE_,
        make sure we have a GOT section.
index 862edae7fb37dcfe4c1627f9cb06851149f55aa1..6937741841ff2c51c5ff1d8a7d84a5868118101a 100644 (file)
 #include <unistd.h>
 
 #include "parameters.h"
+#include "options.h"
 #include "gold-threads.h"
 #include "descriptors.h"
 
+// Very old systems may not define FD_CLOEXEC.
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+// O_CLOEXEC is only available on newer systems.
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
 namespace gold
 {
 
@@ -87,6 +98,10 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode)
 
   while (true)
     {
+      // We always want to set the close-on-exec flag; we don't
+      // require callers to pass it.
+      flags |= O_CLOEXEC;
+
       int new_descriptor = ::open(name, flags, mode);
       if (new_descriptor < 0
          && errno != ENFILE
@@ -109,24 +124,35 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode)
 
       if (new_descriptor >= 0)
        {
-         Hold_optional_lock hl(this->lock_);
-
-         if (static_cast<size_t>(new_descriptor)
-             >= this->open_descriptors_.size())
-           this->open_descriptors_.resize(new_descriptor + 64);
-
-         Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
-         pod->name = name;
-         pod->stack_next = -1;
-         pod->inuse = true;
-         pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
-         pod->is_on_stack = false;
-
-         ++this->current_;
-         if (this->current_ >= this->limit_)
-           this->close_some_descriptor();
-
-         return new_descriptor;
+         // If we have any plugins, we really do need to set the
+         // close-on-exec flag, even if O_CLOEXEC is not defined.
+         // FIXME: In some cases O_CLOEXEC may be defined in the
+         // header file but not supported by the kernel.
+         // Unfortunately there doesn't seem to be any obvious way to
+         // detect that, as unknown flags passed to open are ignored.
+         if (O_CLOEXEC == 0 && parameters->options().has_plugins())
+           fcntl(new_descriptor, F_SETFD, FD_CLOEXEC);
+
+         {
+           Hold_optional_lock hl(this->lock_);
+
+           if (static_cast<size_t>(new_descriptor)
+               >= this->open_descriptors_.size())
+             this->open_descriptors_.resize(new_descriptor + 64);
+
+           Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
+           pod->name = name;
+           pod->stack_next = -1;
+           pod->inuse = true;
+           pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
+           pod->is_on_stack = false;
+
+           ++this->current_;
+           if (this->current_ >= this->limit_)
+             this->close_some_descriptor();
+
+           return new_descriptor;
+         }
        }
 
       // We ran out of file descriptors.