Discussion:
[asio-users] async_read: illegal instruction
Pascal Kesseli
2012-04-23 09:25:56 UTC
Permalink
Hi everyone

Since having updated to boost version 1.48, I am experiencing severe =

runtime errors when relying on asynchronous operations. Please consider =
=

the following code (the important bit is located in ServerReceive=E2=80=99=
s =

operator() ):

=3D=3D=3D main.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
#include <boost/exception/all.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>

using namespace boost;
using namespace boost::asio;
using namespace boost::posix_time;
using namespace boost::system;
using namespace std;

namespace {

const char * const CONNECTION_UNAVAILABLE("error.connection-unavailable"=
);
const char * const RESOLVE_ERROR("error.resolve");
struct host_name;
struct port_value;

ip::tcp::endpoint createEndpoint(const string &hostName, unsigned int =

port) {
io_service ioService;
ip::tcp::resolver resolver(ioService);
ip::tcp::resolver::query query(hostName, lexical_cast<string>(port), =

ip::tcp::resolver::query::numeric_service);
try {
ip::tcp::resolver::iterator resolve(resolver.resolve(query));
if (resolve !=3D ip::tcp::resolver::iterator()) {
return *resolve;
}
} catch (...) {
error_info<host_name, string> nameInfo(hostName);
error_info<port_value, unsigned int> portInfo(port);
exception_ptr nested(current_exception());
runtime_error error(RESOLVE_ERROR);
BOOST_THROW_EXCEPTION(enable_error_info(error) << nameInfo << portInfo <=
< =

errinfo_nested_exception(nested));
}
error_info<host_name, string> nameInfo(hostName);
error_info<port_value, unsigned int> portInfo(port);
BOOST_THROW_EXCEPTION(enable_error_info(runtime_error(CONNECTION_UNAVAIL=
ABLE)) =

<< nameInfo << portInfo);
}

class ServerReceive {
private:
volatile bool ready;
string result;
public:
ServerReceive() :
ready(false) {
}
~ServerReceive() {
}
void operator()() {
io_service io;
try {
ip::tcp::socket socket(io);
ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 32768));=

acceptor.listen();
ready =3D true;
acceptor.accept(socket);
char data[] =3D { '\0', '\0', '\0', '\0', '\0' };
// SYNCHRONOUS CALL
read(socket, buffer(data, 4));
// SYNCHRONOUS CALL
result =3D data;
} catch (const std::exception &ex) {
result =3D ex.what();
ready =3D true;
}
}

const string &getResult() const {
return result;
}

volatile bool isReady() const {
return ready;
}
};

}

int main(int argc, char *argv[]) {
ServerReceive serverReceive;
thread server(ref(serverReceive));
while (!serverReceive.isReady()) {
this_thread::sleep(milliseconds(100));
}
io_service io;
ip::tcp::socket socket(io);
socket.connect(createEndpoint("127.0.0.1", 32768));
asio::write(socket, buffer("asdf", 4));
server.join();
cout << "Result: " << serverReceive.getResult() << endl;
}
=3D=3D=3D main.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D


While this example works like a charm:
=3D=3D=3D output =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
***@target:/tmp/sync# ./sync
=E2=80=9CResult: asdf=E2=80=9D
=3D=3D=3D output =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Using an equivalent asynchronous operation will result in an =E2=80=9Cil=
legal =

instruction=E2=80=9D error:
void onSuccess(const error_code &error, size_t bytes_transferred) {
=3D=3D=3D main.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
// ...
}
// ...
async_read(socket, buffer(data, 4), &onSuccess);
io.run();
=3D=3D=3D main.cpp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

=3D=3D=3D output =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
***@target:/tmp/async# ./async
Illegal instruction
=3D=3D=3D output =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

I am compiling the executable with the following gcc 4.4.2 command:

=3D=3D=3D command =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
xscale-linux-g++ -fPIC -DBOOST_ASIO_DISABLE_EPOLL =

-I/var/lib/c++/boost/boost_1_48_0/target/arm-linux-4.4.2/include -oasync=
=

main.cpp =

-L/var/lib/c++/boost/boost_1_48_0/target/arm-linux-4.4.2/lib/static =

-pthread -lboost_system -lboost_thread
=3D=3D=3D command =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Is this a common or known issue and does anyone have any idea as to how =
to =

address it?

Thanks for any hints and best regards
Pascal
Igor R
2012-04-23 10:08:17 UTC
Permalink
Post by Pascal Kesseli
Since having updated to boost version 1.48, I am experiencing severe
runtime errors when relying on asynchronous operations. Please consider
the following code (the important bit is located in ServerReceive’s
<...>
Post by Pascal Kesseli
void operator()() {
io_service io;
try {
ip::tcp::socket socket(io);
ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 32768));
acceptor.listen();
ready = true;
acceptor.accept(socket);
char data[] = { '\0', '\0', '\0', '\0', '\0' };
// SYNCHRONOUS CALL
read(socket, buffer(data, 4));
// SYNCHRONOUS CALL
result = data;
} catch (const std::exception &ex) {
result = ex.what();
ready = true;
}
}
<...>
Post by Pascal Kesseli
Is this a common or known issue and does anyone have any idea as to how to
address it?
It's a bug in your code.
When calling async functions, you should care that all the buffers and
handlers outlive these operations. Of course, you can't read into
local buffers.
Pascal Kesseli
2012-04-23 11:20:21 UTC
Permalink
Thanks for your swift reply. The asynchronous version would look like th=
is:

void operator()() {
io_service io;
try {
ip::tcp::socket socket(io);
ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 32768)=
);
acceptor.listen();
ready =3D true;
acceptor.accept(socket);
char data[] =3D { '\0', '\0', '\0', '\0', '\0' };
async_read(socket, buffer(data, 4), &onSuccess);
io.run();
result =3D data;
} catch (const std::exception &ex) {
result =3D ex.what();
ready =3D true;
}
}

As far as I've come to unterstand, io.run() will block until all schedul=
ed =

operations have been completed, won't it?
Using a local buffer should therefore not pose any problems.
Post by Igor R
Post by Pascal Kesseli
Since having updated to boost version 1.48, I am experiencing severe
runtime errors when relying on asynchronous operations. Please consid=
er
Post by Igor R
Post by Pascal Kesseli
the following code (the important bit is located in ServerReceive=E2=80=
=99s
Post by Igor R
<...>
Post by Pascal Kesseli
void operator()() {
io_service io;
try {
ip::tcp::socket socket(io);
ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 32768=
));
Post by Igor R
Post by Pascal Kesseli
acceptor.listen();
ready =3D true;
acceptor.accept(socket);
char data[] =3D { '\0', '\0', '\0', '\0', '\0' };
// SYNCHRONOUS CALL
read(socket, buffer(data, 4));
// SYNCHRONOUS CALL
result =3D data;
} catch (const std::exception &ex) {
result =3D ex.what();
ready =3D true;
}
}
<...>
Post by Pascal Kesseli
Is this a common or known issue and does anyone have any idea as to h=
ow =
Post by Igor R
Post by Pascal Kesseli
to
address it?
It's a bug in your code.
When calling async functions, you should care that all the buffers and=
handlers outlive these operations. Of course, you can't read into
local buffers.
----------------------------------------------------------------------=
--------
Post by Igor R
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
asio-users mailing list
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
-- =

Erstellt mit Operas revolution=C3=A4rem E-Mail-Modul: http://www.opera.c=
om/mail/
Igor R
2012-04-23 12:28:55 UTC
Permalink
Post by Pascal Kesseli
void operator()() {
       io_service io;
       try {
               ip::tcp::socket socket(io);
               ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 32768));
               acceptor.listen();
               ready = true;
               acceptor.accept(socket);
               char data[] = { '\0', '\0', '\0', '\0', '\0' };
               async_read(socket, buffer(data, 4), &onSuccess);
You mean something like async_read(socket, buffer(data, 4),
boost::bind(&onSuccess, _1, _2));
Post by Pascal Kesseli
               io.run();
               result = data;
       } catch (const std::exception &ex) {
               result = ex.what();
               ready = true;
       }
}
As far as I've come to unterstand, io.run() will block until all scheduled
operations have been completed, won't it?
Using a local buffer should therefore not pose any problems.
Yes, the above code seems to be ok, and doesn't crash on my machine
(Win7, MSVC10, boost1.49).
So, if it still crashes, the problem might be in some other place.
Perhaps in onSuccess function you haven't shown?
Pascal Kesseli
2012-04-23 13:14:30 UTC
Permalink
onSuccess is empty in this test scenario:

namespace {
void onSuccess(const error_code &error, size_t bytes_transferred) {
}
}

I did, however, use the function directly rather than wrapping it in a =

bind-functor. Is that an issue?

The test program crashes only on one of my target platforms. This =

particular one does not feature EPOLL:
Linux Moxa 2.6.23.1 #1044 Fri May 6 10:25:20 CST 2011 armv5teb GNU/Linux=
Post by Igor R
Thanks for your swift reply. The asynchronous version would look like=
=
Post by Igor R
void operator()() {
io_service io;
try {
ip::tcp::socket socket(io);
ip::tcp::acceptor acceptor(io, =
ip::tcp::endpoint(ip::tcp::v4(), 32768));
acceptor.listen();
ready =3D true;
acceptor.accept(socket);
char data[] =3D { '\0', '\0', '\0', '\0', '\0' };
async_read(socket, buffer(data, 4), &onSuccess);
You mean something like async_read(socket, buffer(data, 4),
boost::bind(&onSuccess, _1, _2));
io.run();
result =3D data;
} catch (const std::exception &ex) {
result =3D ex.what();
ready =3D true;
}
}
As far as I've come to unterstand, io.run() will block until all =
scheduled
operations have been completed, won't it?
Using a local buffer should therefore not pose any problems.
Yes, the above code seems to be ok, and doesn't crash on my machine
(Win7, MSVC10, boost1.49).
So, if it still crashes, the problem might be in some other place.
Perhaps in onSuccess function you haven't shown?
----------------------------------------------------------------------=
--------
Post by Igor R
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
asio-users mailing list
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
-- =

Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/=
mail/
Igor R
2012-04-23 13:42:11 UTC
Permalink
Post by Pascal Kesseli
namespace {
void onSuccess(const error_code &error, size_t bytes_transferred) {
}
}
I did, however, use the function directly rather than wrapping it in a
bind-functor. Is that an issue?
No, sorry, it was absolutely ok without bind.

Loading...