Calling .get on call result blocks (RPC from C++ to Python)

#1

Hi folks,

The small program below blocks on the f.get() call:

#include “autobahn.hpp”

#include

#include

#include <boost/asio.hpp>

#include <boost/version.hpp>

using namespace std;

using namespace boost;

using namespace autobahn;

using boost::asio::ip::tcp;

/*

  • Trying out Autobahn|CPP.

*/

int main(int argc, char *argv[]) {

cerr << "Running on " << BOOST_VERSION << endl;

try {

	// ASIO service object.

	asio::io_service io;

	// The TCP socket we connect.

	tcp::socket socket(io);

	// Connect to localhost.

	tcp::resolver resolver(io);

	auto endpoint_iterator = resolver.resolve({"127.0.0.1", "8090"});

	// Create a WAMP session that talks over TCP.

	bool debug = false;

	autobahn::session<tcp::socket, tcp::socket> session(io, socket, socket, debug);

	// Make sure session join result survives.

	future<void> session_future;

	// Connect to server.

	boost::asio::async_connect(socket, endpoint_iterator,

	                           [&](boost::system::error_code error_code, tcp::resolver::iterator) {

		if (!error_code) {

			cerr << "Connected to server" << endl;

			// Start the WAMP session.

			session.start();

			// Join the "orexplore" realm.

			session_future = session.join("orexplore").then([&](future<uint64_t> s) {

				cerr << "Session joined to realm with session ID " << s.get() << endl;

				auto c1 = session.call("com.orexplore.lamp.set_state", {true}).then([&](future<any> f) {

					std::cerr << "Got result" << std::endl;

					std::cerr << any_cast<bool> (f.get()) << std::endl;

					std::cerr << "Did we get here?" << std::endl;

				});

			});

		} else {

			cerr << "Could not connect to server: " << error_code.message() << endl;

		}

	});

	io.run();

	return 0;

} catch (std::exception& e) {

	cerr << e.what() << endl;

	return 1;

}

}

I.e. the output is

Running on 105700

Connected to server

Session joined to realm with session ID 887748283

Got result

and nothing more (blocks at this point).

If I understand correctly, f.get() should not block at that point, since it is inside the lambda passed to the .when(…) call on the .call() return value, so the result from the RPC call should be immediately available there, right?

The callee is a method in an Autobahn|Python component hosted by Crossbar which returns a Deferred and later calls .callback(True) on it. From looking at logs for that component, everything seems fine on that side.

And the C++ program (which I run manually btw) is getting some answer, since “Got result” is printed. But I’m puzzled by the blocking f.get().

Any advise / ideas are much appreciated.

Cheers,

Elvis

0 Likes

#2

Hi folks,

The small program below blocks on the f.get() call:

#include "autobahn.hpp"

#include <string>
#include <iostream>

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

using namespace std;
using namespace boost;
using namespace autobahn;

using boost::asio::ip::tcp;

/*
* Trying out Autobahn|CPP.
*/
int main(int argc, char *argv[]) {
cerr << "Running on " << BOOST_VERSION << endl;
try {
// ASIO service object.
asio::io_service io;

// The TCP socket we connect.
tcp::socket socket(io);
// Connect to localhost.
tcp::resolver resolver(io);
auto endpoint_iterator = resolver.resolve({"127.0.0.1", "8090"});
// Create a WAMP session that talks over TCP.
bool debug = false;
autobahn::session<tcp::socket, tcp::socket> session(io, socket, socket,
debug);
// Make sure session join result survives.
future<void> session_future;
// Connect to server.
boost::asio::async_connect(socket, endpoint_iterator,
                           [&](boost::system::error_code error_code,
tcp::resolver::iterator) {
if (!error_code) {
cerr << "Connected to server" << endl;
// Start the WAMP session.
session.start();
// Join the "orexplore" realm.
session_future = session.join("orexplore").then([&](future<uint64_t> s) {

cerr << "Session joined to realm with session ID " << s.get() << endl;

auto c1 = session.call("com.orexplore.lamp.set_state",
{true}).then([&](future<any> f) {
std::cerr << "Got result" << std::endl;
std::cerr << any_cast<bool> (f.get()) << std::endl;
std::cerr << "Did we get here?" << std::endl;
});
});
} else {
cerr << "Could not connect to server: " << error_code.message() << endl;
}
});
io.run();
return 0;
} catch (std::exception& e) {
cerr << e.what() << endl;
return 1;
}
}

I.e. the output is

  Running on 105700
  Connected to server
  Session joined to realm with session ID 887748283
  Got result

and nothing more (blocks at this point).

Aha. A finding: If I make sure to call .then(..) also on c1 (the return
value from the .call(...)), it works. Now I just need to understand why :slight_smile:

If anyone can explain it, that would be great. Although I've coded quite a
bit of C++, I'm a little bit need to all these bleeding edge constructs.

Elvis

···

2015-03-21 22:41 GMT+01:00 Elvis Stansvik <elvs...@gmail.com>:

If I understand correctly, f.get() should not block at that point, since
it is inside the lambda passed to the .when(..) call on the .call() return
value, so the result from the RPC call should be immediately available
there, right?

The callee is a method in an Autobahn|Python component hosted by Crossbar
which returns a Deferred and later calls .callback(True) on it. From
looking at logs for that component, everything seems fine on that side.

And the C++ program (which I run manually btw) is getting some answer,
since "Got result" is printed. But I'm puzzled by the blocking f.get().

Any advise / ideas are much appreciated.

Cheers,
Elvis

0 Likes