getdtablesize.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* getdtablesize() function: Return maximum possible file descriptor value + 1.
  2. Copyright (C) 2008-2023 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2008.
  4. This file is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. This file 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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser 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