1// 2// detail/impl/pipe_select_interrupter.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP 12#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP 13 14 15#include "asio/detail/config.hpp" 16 17 18#include <fcntl.h> 19#include <sys/stat.h> 20#include <sys/types.h> 21#include <unistd.h> 22#include "asio/detail/pipe_select_interrupter.hpp" 23#include "asio/detail/socket_types.hpp" 24#include "asio/detail/throw_error.hpp" 25#include "asio/error.hpp" 26 27#include "asio/detail/push_options.hpp" 28 29namespace asio { 30namespace detail { 31 32pipe_select_interrupter::pipe_select_interrupter() 33{ 34 open_descriptors(); 35} 36 37void pipe_select_interrupter::open_descriptors() 38{ 39 int pipe_fds[2]; 40 if (pipe(pipe_fds) == 0) 41 { 42 read_descriptor_ = pipe_fds[0]; 43 ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); 44 write_descriptor_ = pipe_fds[1]; 45 ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); 46 47#if defined(FD_CLOEXEC) 48 ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); 49 ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); 50#endif // defined(FD_CLOEXEC) 51 } 52 else 53 { 54 asio::error_code ec(errno, 55 asio::error::get_system_category()); 56 asio::detail::throw_error(ec, "pipe_select_interrupter"); 57 } 58} 59 60pipe_select_interrupter::~pipe_select_interrupter() 61{ 62 close_descriptors(); 63} 64 65void pipe_select_interrupter::close_descriptors() 66{ 67 if (read_descriptor_ != -1) 68 ::close(read_descriptor_); 69 if (write_descriptor_ != -1) 70 ::close(write_descriptor_); 71} 72 73void pipe_select_interrupter::recreate() 74{ 75 close_descriptors(); 76 77 write_descriptor_ = -1; 78 read_descriptor_ = -1; 79 80 open_descriptors(); 81} 82 83void pipe_select_interrupter::interrupt() 84{ 85 char byte = 0; 86 signed_size_type result = ::write(write_descriptor_, &byte, 1); 87 (void)result; 88} 89 90bool pipe_select_interrupter::reset() 91{ 92 for (;;) 93 { 94 char data[1024]; 95 signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data)); 96 if (bytes_read < 0 && errno == EINTR) 97 continue; 98 bool was_interrupted = (bytes_read > 0); 99 while (bytes_read == sizeof(data)) 100 bytes_read = ::read(read_descriptor_, data, sizeof(data)); 101 return was_interrupted; 102 } 103} 104 105} // namespace detail 106} // namespace asio 107 108#include "asio/detail/pop_options.hpp" 109 110 111#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP 112