fd_deleter.hpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * https://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * Copyright (c) 2023 Andrey Semashev
  7. */
  8. /*!
  9. * \file scope/fd_deleter.hpp
  10. *
  11. * This header contains definition of a deleter function object for
  12. * POSIX-like file descriptors for use with \c unique_resource.
  13. */
  14. #ifndef BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
  15. #define BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
  16. #include <boost/scope/detail/config.hpp>
  17. #if !defined(BOOST_WINDOWS)
  18. #include <unistd.h>
  19. #if defined(hpux) || defined(_hpux) || defined(__hpux)
  20. #include <cerrno>
  21. #endif
  22. #else // !defined(BOOST_WINDOWS)
  23. #include <io.h>
  24. #endif // !defined(BOOST_WINDOWS)
  25. #include <boost/scope/detail/header.hpp>
  26. #ifdef BOOST_HAS_PRAGMA_ONCE
  27. #pragma once
  28. #endif
  29. namespace boost {
  30. namespace scope {
  31. //! POSIX-like file descriptor deleter
  32. struct fd_deleter
  33. {
  34. using result_type = void;
  35. //! Closes the file descriptor
  36. result_type operator() (int fd) const noexcept
  37. {
  38. #if !defined(BOOST_WINDOWS)
  39. #if defined(hpux) || defined(_hpux) || defined(__hpux)
  40. // Some systems don't close the file descriptor in case if the thread is interrupted by a signal and close(2) returns EINTR.
  41. // Other (most) systems do close the file descriptor even when when close(2) returns EINTR, and attempting to close it
  42. // again could close a different file descriptor that was opened by a different thread.
  43. //
  44. // Future POSIX standards will likely fix this by introducing posix_close (see https://www.austingroupbugs.net/view.php?id=529)
  45. // and prohibiting returning EINTR from close(2), but we still have to support older systems where this new behavior is not available and close(2)
  46. // behaves differently between systems.
  47. int res;
  48. while (true)
  49. {
  50. res = ::close(fd);
  51. if (BOOST_UNLIKELY(res < 0))
  52. {
  53. int err = errno;
  54. if (err == EINTR)
  55. continue;
  56. }
  57. break;
  58. }
  59. #else
  60. ::close(fd);
  61. #endif
  62. #else // !defined(BOOST_WINDOWS)
  63. ::_close(fd);
  64. #endif // !defined(BOOST_WINDOWS)
  65. }
  66. };
  67. } // namespace scope
  68. } // namespace boost
  69. #include <boost/scope/detail/footer.hpp>
  70. #endif // BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_