diff --git a/src/impl/apple/external_commit_helper.cpp b/src/impl/apple/external_commit_helper.cpp index db04a1de..5195a3e3 100644 --- a/src/impl/apple/external_commit_helper.cpp +++ b/src/impl/apple/external_commit_helper.cpp @@ -35,7 +35,7 @@ using namespace realm::_impl; namespace { // Write a byte to a pipe to notify anyone waiting for data on the pipe -void notify_fd(int fd) +void notify_fd(int fd, int read_fd) { while (true) { char c = 0; @@ -50,7 +50,7 @@ void notify_fd(int fd) // write. assert(ret == -1 && errno == EAGAIN); char buff[1024]; - read(fd, buff, sizeof buff); + read(read_fd, buff, sizeof buff); } } } // anonymous namespace @@ -94,6 +94,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) throw std::system_error(errno, std::system_category()); } +#if !TARGET_OS_TV auto path = parent.get_path() + ".note"; // Create and open the named pipe @@ -129,15 +130,29 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) throw std::system_error(errno, std::system_category()); } - // Create the anonymous pipe - int pipeFd[2]; - ret = pipe(pipeFd); +#else // !TARGET_OS_TV + + // tvOS does not support named pipes, so use an anonymous pipe instead + int notification_pipe[2]; + int ret = pipe(notification_pipe); if (ret == -1) { throw std::system_error(errno, std::system_category()); } - m_shutdown_read_fd = pipeFd[0]; - m_shutdown_write_fd = pipeFd[1]; + m_notify_fd = notification_pipe[0]; + m_notify_fd_write = notification_pipe[1]; + +#endif // TARGET_OS_TV + + // Create the anonymous pipe for shutdown notifications + int shutdown_pipe[2]; + ret = pipe(shutdown_pipe); + if (ret == -1) { + throw std::system_error(errno, std::system_category()); + } + + m_shutdown_read_fd = shutdown_pipe[0]; + m_shutdown_write_fd = shutdown_pipe[1]; m_thread = std::async(std::launch::async, [=] { try { @@ -158,7 +173,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) ExternalCommitHelper::~ExternalCommitHelper() { - notify_fd(m_shutdown_write_fd); + notify_fd(m_shutdown_write_fd, m_shutdown_read_fd); m_thread.wait(); // Wait for the thread to exit } @@ -202,5 +217,10 @@ void ExternalCommitHelper::listen() void ExternalCommitHelper::notify_others() { - notify_fd(m_notify_fd); + if (m_notify_fd_write != -1) { + notify_fd(m_notify_fd_write, m_notify_fd); + } + else { + notify_fd(m_notify_fd, m_notify_fd); + } } diff --git a/src/impl/apple/external_commit_helper.hpp b/src/impl/apple/external_commit_helper.hpp index a39876ce..c87d8b24 100644 --- a/src/impl/apple/external_commit_helper.hpp +++ b/src/impl/apple/external_commit_helper.hpp @@ -61,16 +61,20 @@ private: // The listener thread std::future m_thread; - // Read-write file descriptor for the named pipe which is waited on for - // changes and written to when a commit is made + // Pipe which is waited on for changes and written to when there is a new + // commit to notify others of. When using a named pipe m_notify_fd is + // read-write and m_notify_fd_write is unused; when using an anonymous pipe + // (on tvOS) m_notify_fd is read-only and m_notify_fd_write is write-only. FdHolder m_notify_fd; + FdHolder m_notify_fd_write; + // File descriptor for the kqueue FdHolder m_kq; + // The two ends of an anonymous pipe used to notify the kqueue() thread that // it should be shut down. FdHolder m_shutdown_read_fd; FdHolder m_shutdown_write_fd; }; - } // namespace _impl } // namespace realm