/* BFD library -- caching of file descriptors.
- Copyright 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002,
- 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1990-2016 Free Software Foundation, Inc.
Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
regard to the underlying operating system's file descriptor
limit (often as low as 20 open files). The module in
<<cache.c>> maintains a least recently used list of
- <<BFD_CACHE_MAX_OPEN>> files, and exports the name
+ <<bfd_cache_max_open>> files, and exports the name
<<bfd_cache_lookup>>, which runs around and makes sure that
the required BFD is open. If not, then it chooses a file to
close, closes it and opens the one wanted, returning its file
};
/* The maximum number of files which the cache will keep open at
- one time. */
+ one time. When needed call bfd_cache_max_open to initialize. */
-#define BFD_CACHE_MAX_OPEN 10
+static int max_open_files = 0;
+
+/* Set max_open_files, if not already set, to 12.5% of the allowed open
+ file descriptors, but at least 10, and return the value. */
+static int
+bfd_cache_max_open (void)
+{
+ if (max_open_files == 0)
+ {
+ int max;
+#if defined(__sun) && !defined(__sparcv9) && !defined(__x86_64__)
+ /* PR ld/19260: 32-bit Solaris has very inelegant handling of the 255
+ file descriptor limit. The problem is that setrlimit(2) can raise
+ RLIMIT_NOFILE to a value that is not supported by libc, resulting
+ in "Too many open files" errors. This can happen here even though
+ max_open_files is set to rlim.rlim_cur / 8. For example, if
+ a parent process has set rlim.rlim_cur to 65536, then max_open_files
+ will be computed as 8192.
+
+ This check essentially reverts to the behavior from binutils 2.23.1
+ for 32-bit Solaris only. (It is hoped that the 32-bit libc
+ limitation will be removed soon). 64-bit Solaris libc does not have
+ this limitation. */
+ max = 16;
+#else
+#ifdef HAVE_GETRLIMIT
+ struct rlimit rlim;
+
+ if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
+ max = rlim.rlim_cur / 8;
+ else
+#endif
+#ifdef _SC_OPEN_MAX
+ max = sysconf (_SC_OPEN_MAX) / 8;
+#else
+ max = 10;
+#endif
+#endif /* not 32-bit Solaris */
+
+ max_open_files = max < 10 ? 10 : max;
+ }
+
+ return max_open_files;
+}
/* The number of BFD files we have open. */
/* Called when the macro <<bfd_cache_lookup>> fails to find a
quick answer. Find a file descriptor for @var{abfd}. If
necessary, it open it. If there are already more than
- <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
+ <<bfd_cache_max_open>> files open, it tries to close one first, to
avoid running out of file descriptors. It will return NULL
if it is unable to (re)open the @var{abfd}. */
if ((abfd->flags & BFD_IN_MEMORY) != 0)
abort ();
- while (abfd->my_archive)
+ while (abfd->my_archive != NULL
+ && !bfd_is_thin_archive (abfd->my_archive))
abfd = abfd->my_archive;
if (abfd->iostream != NULL)
else
return (FILE *) abfd->iostream;
- (*_bfd_error_handler) (_("reopening %B: %s\n"),
- orig_bfd, bfd_errmsg (bfd_get_error ()));
+ /* xgettext:c-format */
+ _bfd_error_handler (_("reopening %B: %s\n"),
+ orig_bfd, bfd_errmsg (bfd_get_error ()));
return NULL;
}
if (nread == (file_ptr)-1)
{
bfd_set_error (bfd_error_system_call);
- return -1;
+ return nread;
}
#else
nread = fread (buf, 1, nbytes, f);
if (nread < nbytes && ferror (f))
{
bfd_set_error (bfd_error_system_call);
- return -1;
+ return nread;
}
#endif
if (nread < nbytes)
return nwrite;
}
-static bfd_boolean
+static int
cache_bclose (struct bfd *abfd)
{
- return bfd_cache_close (abfd);
+ return bfd_cache_close (abfd) - 1;
}
static int
pagesize_m1 = getpagesize () - 1;
/* Handle archive members. */
- if (abfd->my_archive != NULL)
+ if (abfd->my_archive != NULL
+ && !bfd_is_thin_archive (abfd->my_archive))
offset += abfd->origin;
/* Align. */
bfd_cache_init (bfd *abfd)
{
BFD_ASSERT (abfd->iostream != NULL);
- if (open_files >= BFD_CACHE_MAX_OPEN)
+ if (open_files >= bfd_cache_max_open ())
{
if (! close_one ())
return FALSE;
*/
bfd_boolean
-bfd_cache_close_all ()
+bfd_cache_close_all (void)
{
bfd_boolean ret = TRUE;
{
abfd->cacheable = TRUE; /* Allow it to be closed later. */
- if (open_files >= BFD_CACHE_MAX_OPEN)
+ if (open_files >= bfd_cache_max_open ())
{
if (! close_one ())
return NULL;