2014-05-12 9 views
5

voglio fare lettura asincrono da cin quindi ho un pezzo di codiceStrano eccezione tiro - assegnare: Operation not permitted

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

Il problema è: quando eseguo il mio client nel modo normale [./client] e poi inserisco qualcosa via comando, funziona come un incantesimo. Tuttavia, quando l'eseguo tramite [./client < prova] getta:

Termina chiamata dopo aver lanciato un'istanza di 'boost :: :: exception_detail clone_impl

' quello che() : assegnare: Operation not permitted interrotta

hai un'idea di che cosa il problema potrebbe essere? Grazie!

+2

Non hai menzionato quale piattaforma stai usando. Il supporto per I/O file asincroni è molto diverso su Windows e Linux (e ....) –

+0

im usando linux mint 16 64bit – darenn

+0

Dai un'occhiata a strace per vedere cosa potrebbe lamentare syscall. – sehe

risposta

9

Boost.I descrittori orientati al flusso POSIX di Asio non supportano esplicitamente i file normali. Quindi, se test è un file normale, allora ./client < test provocherà un errore nel posix::stream_descriptor::assign() quando si tenta di assegnare STDIN_FILENO allo stream_descriptor. I documentation afferma:

Boost.Asio include classi aggiunte per permettere lettura sincrona e asincrona e scrittura da eseguire su descrittori di file POSIX, come tubi, standard input e di output, e vari dispositivi (ma non file regolari).

consideri passando il contenuto del file di test-client attraverso un tubo.

$ cat test | ./client 

Ecco un programma di esempio completo e dimostrazione:

#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(); 
} 

Dimostrazione

 
$ ./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 
+0

Grazie mille, spiega tutto! – darenn

0

Puoi provare con questo riproduttore minimale? Funziona sulla mia Ubuntu box a 64 bit:

#include <boost/asio.hpp> 
#include <boost/asio/posix/stream_descriptor.hpp> 

#include <iostream> 

int main() 
{ 
    using namespace boost::asio; 

    io_service io; 
    posix::stream_descriptor input(io); 

    input.assign(STDIN_FILENO); 
    streambuf input_buffer; 

    std::function<void()> loop = [&] { 
     async_read_until(input, input_buffer, '\n', [&](boost::system::error_code ec, size_t) { 
      if (ec) 
       std::cerr << ec.message(); 
      else { 
       std::cout << "LOOP: '" << &input_buffer << "'\n"; 
       loop(); 
      } 
     }); 
    }; 

    loop(); 
    io.run(); 
} 

Aggiornamento penso di poter riprodurre il problema on Coliru: si può controllare l'uscita di ulimit -a?

+0

anche quando si passa un file all'i/o. ecco l'output di ulimit -a: http://pastebin.com/WfpNkGjV – darenn

1

Boost ASIO, su Linux, utilizza il sistema epollby default che does not support files.

Ma c'è una soluzione alternativa: se si definisce BOOST_ASIO_DISABLE_EPOLL, asio tornerà al sistema select ei file funzioneranno.

Problemi correlati