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
15#ifndef BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
16#define BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
17
18#include <boost/scope/detail/config.hpp>
19
20#if !defined(BOOST_WINDOWS)
21#include <unistd.h>
22#if defined(hpux) || defined(_hpux) || defined(__hpux)
23#include <cerrno>
24#endif
25#else // !defined(BOOST_WINDOWS)
26#include <io.h>
27#endif // !defined(BOOST_WINDOWS)
28
29#include <boost/scope/detail/header.hpp>
30
31#ifdef BOOST_HAS_PRAGMA_ONCE
32#pragma once
33#endif
34
35namespace boost {
36namespace scope {
37
38//! POSIX-like file descriptor deleter
39struct fd_deleter
40{
41 using result_type = void;
42
43 //! Closes the file descriptor
44 result_type operator() (int fd) const noexcept
45 {
46#if !defined(BOOST_WINDOWS)
47#if defined(hpux) || defined(_hpux) || defined(__hpux)
48 // Some systems don't close the file descriptor in case if the thread is interrupted by a signal and close(2) returns EINTR.
49 // Other (most) systems do close the file descriptor even when when close(2) returns EINTR, and attempting to close it
50 // again could close a different file descriptor that was opened by a different thread.
51 //
52 // Future POSIX standards will likely fix this by introducing posix_close (see https://www.austingroupbugs.net/view.php?id=529)
53 // 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)
54 // behaves differently between systems.
55 int res;
56 while (true)
57 {
58 res = ::close(fd);
59 if (BOOST_UNLIKELY(res < 0))
60 {
61 int err = errno;
62 if (err == EINTR)
63 continue;
64 }
65
66 break;
67 }
68#else
69 ::close(fd: fd);
70#endif
71#else // !defined(BOOST_WINDOWS)
72 ::_close(fd);
73#endif // !defined(BOOST_WINDOWS)
74 }
75};
76
77} // namespace scope
78} // namespace boost
79
80#include <boost/scope/detail/footer.hpp>
81
82#endif // BOOST_SCOPE_FD_DELETER_HPP_INCLUDED_
83

source code of boost/libs/scope/include/boost/scope/fd_deleter.hpp