2
0
mirror of https://github.com/boostorg/asio.git synced 2026-01-27 06:32:08 +00:00

Add limited support for regular file descriptors.

The epoll_reactor now supports the use of regular file descriptors with
posix::stream_descriptor, provided the I/O operations on them never fail
with EAGAIN or EWOULDBLOCK. If the descriptor cannot be added to the
epoll set using epoll_ctl, and errno is EPERM (indicating an unsupported
descriptor type), then no error condition is raised. Instead, any
operation which would require a trip through the reactor will fail.
This commit is contained in:
Christopher Kohlhoff
2017-03-05 22:56:48 +11:00
parent 49aa5e1e6c
commit fba6c4ccbd
2 changed files with 34 additions and 2 deletions

View File

@@ -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:

View File

@@ -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);