diff --git a/doc/overview/posix.qbk b/doc/overview/posix.qbk index 4d78cced..d7468ea8 100644 --- a/doc/overview/posix.qbk +++ b/doc/overview/posix.qbk @@ -75,7 +75,15 @@ target operating system. A program may test for the macro Boost.Asio includes classes added to permit synchronous and asynchronous read and write operations to be performed on POSIX file descriptors, such as pipes, -standard input and output, and various devices (but /not/ regular files). +standard input and output, and various devices. + +These classes also provide limited support for regular files. This support +assumes that the underlying read and write operations provided by the operating +system never fail with `EAGAIN` or `EWOULDBLOCK`. (This assumption normally +holds for buffered file I/O.) Synchronous and asynchronous read and write +operations on file descriptors will succeed but the I/O will always be +performed immediately. Wait operations, and operations involving +`boost::asio::null_buffers`, are not portably supported. For example, to perform read and write operations on standard input and output, the following objects may be created: diff --git a/include/boost/asio/detail/impl/epoll_reactor.ipp b/include/boost/asio/detail/impl/epoll_reactor.ipp index b6b12a39..610ce31c 100644 --- a/include/boost/asio/detail/impl/epoll_reactor.ipp +++ b/include/boost/asio/detail/impl/epoll_reactor.ipp @@ -164,7 +164,18 @@ int epoll_reactor::register_descriptor(socket_type descriptor, ev.data.ptr = descriptor_data; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); if (result != 0) + { + if (errno == EPERM) + { + // This file descriptor type is not supported by epoll. However, if it is + // a regular file then operations on it will not block. We will allow + // this descriptor to be used and fail later if an operation on it would + // otherwise require a trip through the reactor. + descriptor_data->registered_events_ = 0; + return 0; + } return errno; + } return 0; } @@ -235,6 +246,13 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, return; } + if (descriptor_data->registered_events_ == 0) + { + op->ec_ = boost::asio::error::operation_not_supported; + io_service_.post_immediate_completion(op, is_continuation); + return; + } + if (op_type == write_op) { if ((descriptor_data->registered_events_ & EPOLLOUT) == 0) @@ -256,6 +274,12 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, } } } + else if (descriptor_data->registered_events_ == 0) + { + op->ec_ = boost::asio::error::operation_not_supported; + io_service_.post_immediate_completion(op, is_continuation); + return; + } else { if (op_type == write_op) @@ -313,7 +337,7 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor, // The descriptor will be automatically removed from the epoll set when // it is closed. } - else + else if (descriptor_data->registered_events_ != 0) { epoll_event ev = { 0, { 0 } }; epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);