X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fdescriptors.cc;h=b7fbaa61deb922579a5e84cf42be2e797ae31ae8;hb=d0b5971ae7b8709c28a7a1638413426d8749d976;hp=862edae7fb37dcfe4c1627f9cb06851149f55aa1;hpb=61edd21fa41ccf31fe391ee320c4812c4d45486a;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/descriptors.cc b/gold/descriptors.cc index 862edae7fb..b7fbaa61de 100644 --- a/gold/descriptors.cc +++ b/gold/descriptors.cc @@ -1,6 +1,6 @@ // descriptors.cc -- manage file descriptors for gold -// Copyright 2008, 2009 Free Software Foundation, Inc. +// Copyright 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -23,13 +23,35 @@ #include "gold.h" #include +#include #include #include #include #include "parameters.h" +#include "options.h" #include "gold-threads.h" #include "descriptors.h" +#include "binary-io.h" + +// O_CLOEXEC is only available on newer systems. +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +// Very old systems may not define FD_CLOEXEC. +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +static inline void +set_close_on_exec(int fd ATTRIBUTE_UNUSED) +{ +// Mingw does not define F_SETFD. +#ifdef F_SETFD + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +} namespace gold { @@ -40,8 +62,8 @@ namespace gold // adjusted downward if we run out of file descriptors. Descriptors::Descriptors() - : lock_(NULL), open_descriptors_(), stack_top_(-1), current_(0), - limit_(8192 - 16) + : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(), + stack_top_(-1), current_(0), limit_(8192 - 16) { this->open_descriptors_.reserve(128); } @@ -55,13 +77,9 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) // initialize a Lock until we have parsed the options to find out // whether we are running with threads. We can be called before // options are valid when reading a linker script. - if (this->lock_ == NULL) - { - if (parameters->options_valid()) - this->lock_ = new Lock(); - else - gold_assert(descriptor < 0); - } + bool lock_initialized = this->initialize_lock_.initialize(); + + gold_assert(lock_initialized || descriptor < 0); if (descriptor >= 0) { @@ -87,6 +105,13 @@ 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; + + // Always open the file as a binary file. + flags |= O_BINARY; + int new_descriptor = ::open(name, flags, mode); if (new_descriptor < 0 && errno != ENFILE @@ -97,8 +122,7 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) { Hold_lock hl(*this->lock_); - gold_error(_("file %s was removed during the link"), - this->open_descriptors_[descriptor].name); + gold_error(_("file %s was removed during the link"), name); } errno = ENOENT; @@ -109,24 +133,37 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) if (new_descriptor >= 0) { - Hold_optional_lock hl(this->lock_); - - if (static_cast(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_valid() + && parameters->options().has_plugins()) + set_close_on_exec(new_descriptor); + + { + Hold_optional_lock hl(this->lock_); + + if (static_cast(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. @@ -214,6 +251,28 @@ Descriptors::close_some_descriptor() return false; } +// Close all the descriptors open for reading. + +void +Descriptors::close_all() +{ + Hold_optional_lock hl(this->lock_); + + for (size_t i = 0; i < this->open_descriptors_.size(); i++) + { + Open_descriptor* pod = &this->open_descriptors_[i]; + if (pod->name != NULL && !pod->inuse && !pod->is_write) + { + if (::close(i) < 0) + gold_warning(_("while closing %s: %s"), pod->name, strerror(errno)); + pod->name = NULL; + pod->stack_next = -1; + pod->is_on_stack = false; + } + } + this->stack_top_ = -1; +} + // The single global variable which manages descriptors. Descriptors descriptors;