Commit: Tell users when the plugin interface runs out of file descriptors

Message ID 87h7izf10q.fsf@redhat.com
State New
Headers show
Series
  • Commit: Tell users when the plugin interface runs out of file descriptors
Related show

Commit Message

Alan Modra via Binutils May 19, 2021, 10:53 a.m.
Hi Guys,

  I am applying the patch below which is half bug-fix half-hack.  The
  problem is that the plugin API can run out of file descriptors when
  performing a very large link.  (This was discovered when using ld.bfd
  to link LLVM...)  When this happens the bfd_plugin_open_input()
  function returns 0, which in turn leads to an error message about the
  format of an input file being unrecognizable.  This is obviously
  wrong, and the first part of this patch detects this case and issues a
  second, more explanatory error message.

  A better solution of course would be to recycle the file descriptors
  rather than allocating two per input file and two per member of an
  incoming archive.  But try as I might, I have not found a way to do
  this without breaking the plugin API.  So instead the hacky part of
  the patch attempts to increase the limit on the number of open file
  descriptors, in order to allow the link to continue.  This works for
  the test case mentioned above, but will fail one day.  Still at least
  it works for now.

Cheers
  Nick

bfd/ChangeLog
2021-05-19  Nick Clifton  <nickc@redhat.com>

	* plugin.c (bfd_plugin_open_input): Inform the user if the limit
	on the number of open files is reached.  If possible, try to
	increase this limit before failing.

Patch

diff --git a/bfd/plugin.c b/bfd/plugin.c
index c4f2be8999e..1fee4d0c870 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -209,7 +209,35 @@  bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
      the same underlying file descriptor.  */
   file->fd = open (file->name, O_RDONLY | O_BINARY);
   if (file->fd < 0)
-    return 0;
+    {
+#ifndef EMFILE
+      return 0;
+#else
+      if (errno != EMFILE)
+	return 0;
+
+#ifdef HAVE_GETRLIMIT
+      struct rlimit lim;
+
+      /* Complicated links involving lots of files and/or large archives
+	 can exhaust the number of file descriptors available to us.
+	 If possible, try to allocate more descriptors.  */
+      if (getrlimit (RLIMIT_NOFILE, & lim) == 0
+	  && lim.rlim_cur < lim.rlim_max)
+	{
+	  lim.rlim_cur = lim.rlim_max;
+	  if (setrlimit (RLIMIT_NOFILE, &lim) == 0)
+	    file->fd = open (file->name, O_RDONLY | O_BINARY);
+	}
+
+      if (file->fd < 0)
+#endif
+	{
+	  _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n"));
+	  return 0;
+	} 
+#endif
+   }
 
   if (iobfd == ibfd)
     {