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 29 namespace asio { 30 namespace detail { 31 32 pipe_select_interrupter::pipe_select_interrupter() 33 { 34 open_descriptors(); 35 } 36 37 void 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 60 pipe_select_interrupter::~pipe_select_interrupter() 61 { 62 close_descriptors(); 63 } 64 65 void 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 73 void pipe_select_interrupter::recreate() 74 { 75 close_descriptors(); 76 77 write_descriptor_ = -1; 78 read_descriptor_ = -1; 79 80 open_descriptors(); 81 } 82 83 void pipe_select_interrupter::interrupt() 84 { 85 char byte = 0; 86 signed_size_type result = ::write(write_descriptor_, &byte, 1); 87 (void)result; 88 } 89 90 bool 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