Home | History | Annotate | Download | only in gold
      1 // descriptors.cc -- manage file descriptors for gold
      2 
      3 // Copyright (C) 2008-2016 Free Software Foundation, Inc.
      4 // Written by Ian Lance Taylor <iant (at) google.com>.
      5 
      6 // This file is part of gold.
      7 
      8 // This program is free software; you can redistribute it and/or modify
      9 // it under the terms of the GNU General Public License as published by
     10 // the Free Software Foundation; either version 3 of the License, or
     11 // (at your option) any later version.
     12 
     13 // This program is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // You should have received a copy of the GNU General Public License
     19 // along with this program; if not, write to the Free Software
     20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21 // MA 02110-1301, USA.
     22 
     23 #include "gold.h"
     24 
     25 #include <cerrno>
     26 #include <cstdio>
     27 #include <cstring>
     28 #include <fcntl.h>
     29 #include <unistd.h>
     30 
     31 #include "debug.h"
     32 #include "parameters.h"
     33 #include "options.h"
     34 #include "gold-threads.h"
     35 #include "descriptors.h"
     36 #include "binary-io.h"
     37 
     38 // O_CLOEXEC is only available on newer systems.
     39 #ifndef O_CLOEXEC
     40 #define O_CLOEXEC 0
     41 #endif
     42 
     43 // Very old systems may not define FD_CLOEXEC.
     44 #ifndef FD_CLOEXEC
     45 #define FD_CLOEXEC 1
     46 #endif
     47 
     48 static inline void
     49 set_close_on_exec(int fd ATTRIBUTE_UNUSED)
     50 {
     51 // Mingw does not define F_SETFD.
     52 #ifdef F_SETFD
     53   fcntl(fd, F_SETFD, FD_CLOEXEC);
     54 #endif
     55 }
     56 
     57 namespace gold
     58 {
     59 
     60 // Class Descriptors.
     61 
     62 // The default for limit_ is meant to simply be large.  It gets
     63 // adjusted downward if we run out of file descriptors.
     64 
     65 Descriptors::Descriptors()
     66   : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(),
     67     stack_top_(-1), current_(0), limit_(8192 - 16)
     68 {
     69   this->open_descriptors_.reserve(128);
     70 }
     71 
     72 // Open a file.
     73 
     74 int
     75 Descriptors::open(int descriptor, const char* name, int flags, int mode)
     76 {
     77   // We don't initialize this until we are called, because we can't
     78   // initialize a Lock until we have parsed the options to find out
     79   // whether we are running with threads.  We can be called before
     80   // options are valid when reading a linker script.
     81   bool lock_initialized = this->initialize_lock_.initialize();
     82 
     83   gold_assert(lock_initialized || descriptor < 0);
     84 
     85   if (is_debugging_enabled(DEBUG_FILES))
     86     this->limit_ = 8;
     87 
     88   if (descriptor >= 0)
     89     {
     90       Hold_lock hl(*this->lock_);
     91 
     92       gold_assert(static_cast<size_t>(descriptor)
     93 		  < this->open_descriptors_.size());
     94       Open_descriptor* pod = &this->open_descriptors_[descriptor];
     95       if (pod->name == name
     96 	  || (pod->name != NULL && strcmp(pod->name, name) == 0))
     97 	{
     98 	  gold_assert(!pod->inuse);
     99 	  pod->inuse = true;
    100 	  if (descriptor == this->stack_top_)
    101 	    {
    102 	      this->stack_top_ = pod->stack_next;
    103 	      pod->stack_next = -1;
    104 	      pod->is_on_stack = false;
    105 	    }
    106 	  gold_debug(DEBUG_FILES, "Reused existing descriptor %d for \"%s\"",
    107 		     descriptor, name);
    108 	  return descriptor;
    109 	}
    110     }
    111 
    112   while (true)
    113     {
    114       // We always want to set the close-on-exec flag; we don't
    115       // require callers to pass it.
    116       flags |= O_CLOEXEC;
    117 
    118       // Always open the file as a binary file.
    119       flags |= O_BINARY;
    120 
    121       int new_descriptor = ::open(name, flags, mode);
    122       if (new_descriptor < 0
    123 	  && errno != ENFILE
    124 	  && errno != EMFILE)
    125 	{
    126 	  if (descriptor >= 0 && errno == ENOENT)
    127 	    {
    128 	      {
    129 		Hold_lock hl(*this->lock_);
    130 
    131 		gold_error(_("file %s was removed during the link"), name);
    132 	      }
    133 
    134 	      errno = ENOENT;
    135 	    }
    136 
    137 	  gold_debug(DEBUG_FILES, "Opened new descriptor %d for \"%s\"",
    138 		     new_descriptor, name);
    139 	  return new_descriptor;
    140 	}
    141 
    142       if (new_descriptor >= 0)
    143 	{
    144 	  // If we have any plugins, we really do need to set the
    145 	  // close-on-exec flag, even if O_CLOEXEC is not defined.
    146 	  // FIXME: In some cases O_CLOEXEC may be defined in the
    147 	  // header file but not supported by the kernel.
    148 	  // Unfortunately there doesn't seem to be any obvious way to
    149 	  // detect that, as unknown flags passed to open are ignored.
    150 	  if (O_CLOEXEC == 0
    151 	      && parameters->options_valid()
    152 	      && parameters->options().has_plugins())
    153 	    set_close_on_exec(new_descriptor);
    154 
    155 	  {
    156 	    Hold_optional_lock hl(this->lock_);
    157 
    158 	    if (static_cast<size_t>(new_descriptor)
    159 		>= this->open_descriptors_.size())
    160 	      this->open_descriptors_.resize(new_descriptor + 64);
    161 
    162 	    Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
    163 	    pod->name = name;
    164 	    pod->stack_next = -1;
    165 	    pod->inuse = true;
    166 	    pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
    167 	    pod->is_on_stack = false;
    168 
    169 	    ++this->current_;
    170 	    if (this->current_ >= this->limit_)
    171 	      this->close_some_descriptor();
    172 
    173 	    gold_debug(DEBUG_FILES, "Opened new descriptor %d for \"%s\"",
    174 		       new_descriptor, name);
    175 	    return new_descriptor;
    176 	  }
    177 	}
    178 
    179       // We ran out of file descriptors.
    180       {
    181 	Hold_optional_lock hl(this->lock_);
    182 
    183 	this->limit_ = this->current_ - 16;
    184 	if (this->limit_ < 8)
    185 	  this->limit_ = 8;
    186 	if (!this->close_some_descriptor())
    187 	  gold_fatal(_("out of file descriptors and couldn't close any"));
    188       }
    189     }
    190 }
    191 
    192 // Release a descriptor.
    193 
    194 void
    195 Descriptors::release(int descriptor, bool permanent)
    196 {
    197   Hold_optional_lock hl(this->lock_);
    198 
    199   gold_assert(descriptor >= 0
    200 	      && (static_cast<size_t>(descriptor)
    201 		  < this->open_descriptors_.size()));
    202   Open_descriptor* pod = &this->open_descriptors_[descriptor];
    203 
    204   if (permanent
    205       || (this->current_ > this->limit_ && !pod->is_write))
    206     {
    207       if (::close(descriptor) < 0)
    208 	gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
    209       pod->name = NULL;
    210       --this->current_;
    211     }
    212   else
    213     {
    214       pod->inuse = false;
    215       if (!pod->is_write && !pod->is_on_stack)
    216 	{
    217 	  pod->stack_next = this->stack_top_;
    218 	  this->stack_top_ = descriptor;
    219 	  pod->is_on_stack = true;
    220 	}
    221     }
    222 
    223   gold_debug(DEBUG_FILES, "Released descriptor %d for \"%s\"",
    224 	     descriptor, pod->name);
    225 }
    226 
    227 // Close some descriptor.  The lock is held when this is called.  We
    228 // close the descriptor on the top of the free stack.  Note that this
    229 // is the opposite of an LRU algorithm--we close the most recently
    230 // used descriptor.  That is because the linker tends to cycle through
    231 // all the files; after we release a file, we are unlikely to need it
    232 // again until we have looked at all the other files.  Return true if
    233 // we closed a descriptor.
    234 
    235 bool
    236 Descriptors::close_some_descriptor()
    237 {
    238   int last = -1;
    239   int i = this->stack_top_;
    240   while (i >= 0)
    241     {
    242       gold_assert(static_cast<size_t>(i) < this->open_descriptors_.size());
    243       Open_descriptor* pod = &this->open_descriptors_[i];
    244       if (!pod->inuse && !pod->is_write)
    245 	{
    246 	  if (::close(i) < 0)
    247 	    gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
    248 	  --this->current_;
    249 	  gold_debug(DEBUG_FILES, "Closed descriptor %d for \"%s\"",
    250 		     i, pod->name);
    251 	  pod->name = NULL;
    252 	  if (last < 0)
    253 	    this->stack_top_ = pod->stack_next;
    254 	  else
    255 	    this->open_descriptors_[last].stack_next = pod->stack_next;
    256 	  pod->stack_next = -1;
    257 	  pod->is_on_stack = false;
    258 	  return true;
    259 	}
    260       last = i;
    261       i = pod->stack_next;
    262     }
    263 
    264   // We couldn't find any descriptors to close.  This is weird but not
    265   // necessarily an error.
    266   return false;
    267 }
    268 
    269 // Close all the descriptors open for reading.
    270 
    271 void
    272 Descriptors::close_all()
    273 {
    274   Hold_optional_lock hl(this->lock_);
    275 
    276   for (size_t i = 0; i < this->open_descriptors_.size(); i++)
    277     {
    278       Open_descriptor* pod = &this->open_descriptors_[i];
    279       if (pod->name != NULL && !pod->inuse && !pod->is_write)
    280 	{
    281 	  if (::close(i) < 0)
    282 	    gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
    283 	  gold_debug(DEBUG_FILES, "Closed descriptor %d for \"%s\" (close_all)",
    284 		     static_cast<int>(i), pod->name);
    285 	  pod->name = NULL;
    286 	  pod->stack_next = -1;
    287 	  pod->is_on_stack = false;
    288 	}
    289     }
    290   this->stack_top_ = -1;
    291 }
    292 
    293 // The single global variable which manages descriptors.
    294 
    295 Descriptors descriptors;
    296 
    297 } // End namespace gold.
    298