Strange exception throw - assign: Operation not permitted

boost, boost-asio, c++

Solution

Boost.Asio's POSIX stream-oriented descriptors explicitly do not support regular files. Hence, if `test` is a regular file, then `./client < test` will result in `posix::stream_descriptor::assign()` failing when attempting to assign `STDIN_FILENO` to the `stream_descriptor`. The documentation states:

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).

Consider passing the contents of the `test` file to `client` through a pipe.

$ cat test | ./client

Here is a complete example program and demonstration:

#include <iostream>
#include <boost/asio.hpp>

void handle_read(
  const boost::system::error_code& error,
  std::size_t bytes_transferred
)
{
  std::cout << "read " << bytes_transferred << " bytes with "
            << error.message() << std::endl;
}

int main()
{
  boost::asio::io_service io_service;
  boost::asio::posix::stream_descriptor input(io_service);

  // Assign STDIN_FILENO to the stream_descriptor.  It will support
  // pipes, standard input and output, and various devices, but NOT
  // regular files.
  boost::system::error_code error;
  input.assign(STDIN_FILENO, error);
  if (error)
  {
    std::cerr << error.message() << std::endl;
    return -1;
  }

  boost::asio::streambuf input_buffer;
  async_read_until(input, input_buffer, '\n', &handle_read);
  io_service.run();
}

Demonstration

$ ./client
testing standard inputenter
read 23 bytes with Success
$ echo "this is a test" > test
$ ./client < test
Operation not permitted
$ cat test | ./client
read 15 bytes with Success

Problem

I want to do asynchronous read from cin therefore I have a piece of code client.h ``` ... boost::asio::posix::stream_descriptor input; boost::asio::streambuf input_buffer ``` client.cpp ``` Client::Client(int argc, char **argv, boost::asio::io_service &io_service) : tcp_socket(io_service) , udp_socket(io_service) , input(io_service, ::dup(STDIN_FILENO)) { ... read_std_input(); } void Client::read_std_input() { async_read_until(input, input_buffer, '\n', boost::bind(&Client::handle_std_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } ``` The problem is: when I run my client the normal way [ ./client ] and then input something via command like, it works like charm. However, when I run it via [ ./client < test ] it throws : terminate called after throwing an instance of 'boost::exception_detail::clone_impl ' what(): assign: Operation not permitted Aborted Do you have an idea of what the problem might be? Thanks!

Original source

Related problems