getdtablesize.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* getdtablesize() function: Return maximum possible file descriptor value + 1.
  2. Copyright (C) 2008-2020 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2008.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <unistd.h>
  17. #if defined _WIN32 && ! defined __CYGWIN__
  18. # include <stdio.h>
  19. # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  20. # include "msvc-inval.h"
  21. # endif
  22. # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  23. static int
  24. _setmaxstdio_nothrow (int newmax)
  25. {
  26. int result;
  27. TRY_MSVC_INVAL
  28. {
  29. result = _setmaxstdio (newmax);
  30. }
  31. CATCH_MSVC_INVAL
  32. {
  33. result = -1;
  34. }
  35. DONE_MSVC_INVAL;
  36. return result;
  37. }
  38. # else
  39. # define _setmaxstdio_nothrow _setmaxstdio
  40. # endif
  41. /* Cache for the previous getdtablesize () result. Safe to cache because
  42. Windows also lacks setrlimit. */
  43. static int dtablesize;
  44. int
  45. getdtablesize (void)
  46. {
  47. if (dtablesize == 0)
  48. {
  49. /* We are looking for the number N such that the valid file descriptors
  50. are 0..N-1. It can be obtained through a loop as follows:
  51. {
  52. int fd;
  53. for (fd = 3; fd < 65536; fd++)
  54. if (dup2 (0, fd) == -1)
  55. break;
  56. return fd;
  57. }
  58. On Windows XP, the result is 2048.
  59. The drawback of this loop is that it allocates memory for a libc
  60. internal array that is never freed.
  61. The number N can also be obtained as the upper bound for
  62. _getmaxstdio (). _getmaxstdio () returns the maximum number of open
  63. FILE objects. The sanity check in _setmaxstdio reveals the maximum
  64. number of file descriptors. This too allocates memory, but it is
  65. freed when we call _setmaxstdio with the original value. */
  66. int orig_max_stdio = _getmaxstdio ();
  67. unsigned int bound;
  68. for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
  69. ;
  70. _setmaxstdio_nothrow (orig_max_stdio);
  71. dtablesize = bound;
  72. }
  73. return dtablesize;
  74. }
  75. #else
  76. # include <limits.h>
  77. # include <sys/resource.h>
  78. # ifndef RLIM_SAVED_CUR
  79. # define RLIM_SAVED_CUR RLIM_INFINITY
  80. # endif
  81. # ifndef RLIM_SAVED_MAX
  82. # define RLIM_SAVED_MAX RLIM_INFINITY
  83. # endif
  84. # ifdef __CYGWIN__
  85. /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it
  86. hits the compile-time constant hard limit of 3200. We might as
  87. well just report the hard limit. */
  88. # define rlim_cur rlim_max
  89. # endif
  90. int
  91. getdtablesize (void)
  92. {
  93. struct rlimit lim;
  94. if (getrlimit (RLIMIT_NOFILE, &lim) == 0
  95. && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX
  96. && lim.rlim_cur != RLIM_INFINITY
  97. && lim.rlim_cur != RLIM_SAVED_CUR
  98. && lim.rlim_cur != RLIM_SAVED_MAX)
  99. return lim.rlim_cur;
  100. return INT_MAX;
  101. }
  102. #endif