diff --git a/doc/release_history.html b/doc/release_history.html
index 206221c..a3f13bb 100644
--- a/doc/release_history.html
+++ b/doc/release_history.html
@@ -45,6 +45,7 @@
Marked templated versions of initial_path as deprecated and removed from v4. Use the non-templated versions instead.
Use readdir instead of readdir_r on more POSIX platforms, specifically on Mac OS and other Apple operating systems, FreeBSD, OpenBSD, DragonFly BSD, NetBSD, QNX 6.0 and later, Solaris 10 and later and Illumos-based systems. Solaris users with gcc are recommended to define __SunOS_5_x macros according to their target Solaris version (e.g. __SunOS_5_11) when building Boost. (#349)
Support for platforms with non-thread-safe readdir is deprecated and will be removed in a future release. Although not required until POSIX.1-2024, on modern systems readdir is thread-safe when used with separate DIR objects in different threads and on some systems readdir_r is marked as deprecated. POSIX.1-2024 has been updated accordingly and also marked readdir_r as obsolescent, with a planned removal in a future version of the specification.
+ On POSIX platforms, handle EINTR error code returned from opendir, readdir and equivalents. Although not documented, this error code, reportedly, may be returned on Apple operating systems and some BSD systems.
1.91.0
diff --git a/src/directory.cpp b/src/directory.cpp
index e593025..31147b2 100644
--- a/src/directory.cpp
+++ b/src/directory.cpp
@@ -417,11 +417,21 @@ inline int invoke_readdir(dir_itr_imp& imp, struct dirent** result)
system::error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_status& sf, fs::file_status& symlink_sf)
{
dirent* result = nullptr;
- int err = invoke_readdir(imp, &result);
- if (BOOST_UNLIKELY(err != 0))
- return system::error_code(err, system::system_category());
- if (result == nullptr)
- return dir_itr_close(imp);
+ while (true)
+ {
+ int err = invoke_readdir(imp, &result);
+ if (BOOST_UNLIKELY(err != 0))
+ {
+ if (err == EINTR)
+ continue;
+ return system::error_code(err, system::system_category());
+ }
+
+ if (result == nullptr)
+ return dir_itr_close(imp);
+
+ break;
+ }
filename = result->d_name;
@@ -511,21 +521,35 @@ system::error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& i
return ec;
}
- pimpl->handle = ::fdopendir(fd.get());
- if (BOOST_UNLIKELY(!pimpl->handle))
+ while (true)
{
- const int err = errno;
- return system::error_code(err, system::system_category());
+ pimpl->handle = ::fdopendir(fd.get());
+ if (BOOST_UNLIKELY(!pimpl->handle))
+ {
+ const int err = errno;
+ if (err == EINTR)
+ continue;
+ return system::error_code(err, system::system_category());
+ }
+
+ break;
}
// At this point fd will be closed by closedir
fd.release();
#else // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
- pimpl->handle = ::opendir(dir.c_str());
- if (BOOST_UNLIKELY(!pimpl->handle))
+ while (true)
{
- const int err = errno;
- return system::error_code(err, system::system_category());
+ pimpl->handle = ::opendir(dir.c_str());
+ if (BOOST_UNLIKELY(!pimpl->handle))
+ {
+ const int err = errno;
+ if (err == EINTR)
+ continue;
+ return system::error_code(err, system::system_category());
+ }
+
+ break;
}
#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
@@ -1118,29 +1142,44 @@ bool is_empty_directory(boost::scope::unique_fd&& fd, path const& p, error_code*
::closedir(dir);
}
};
+ std::unique_ptr< DIR, closedir_deleter > dir;
int err;
#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
- std::unique_ptr< DIR, closedir_deleter > dir(::fdopendir(fd.get()));
- if (BOOST_UNLIKELY(!dir))
+ while (true)
{
- err = errno;
- fail:
- emit_error(err, p, ec, "boost::filesystem::is_empty");
- return false;
+ dir.reset(::fdopendir(fd.get()));
+ if (BOOST_UNLIKELY(!dir))
+ {
+ err = errno;
+ if (err == EINTR)
+ continue;
+ fail:
+ emit_error(err, p, ec, "boost::filesystem::is_empty");
+ return false;
+ }
+
+ break;
}
// At this point fd will be closed by closedir
fd.release();
#else // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
- std::unique_ptr< DIR, closedir_deleter > dir(::opendir(p.c_str()));
- if (BOOST_UNLIKELY(!dir))
+ while (true)
{
- err = errno;
- fail:
- emit_error(err, p, ec, "boost::filesystem::is_empty");
- return false;
+ dir.reset(::opendir(p.c_str()));
+ if (BOOST_UNLIKELY(!dir))
+ {
+ err = errno;
+ if (err == EINTR)
+ continue;
+ fail:
+ emit_error(err, p, ec, "boost::filesystem::is_empty");
+ return false;
+ }
+
+ break;
}
#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
@@ -1151,6 +1190,8 @@ bool is_empty_directory(boost::scope::unique_fd&& fd, path const& p, error_code*
if (!ent)
{
err = errno;
+ if (err == EINTR)
+ continue;
if (err != 0)
goto fail;