descriptors.cc 7.9 KB

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