[Dbus-cxx-devel] problem: multithreaded dbus-cxx apps
Status: Beta
Brought to you by:
rvinyard
From: Oliver K. <oli...@se...> - 2009-09-15 15:00:07
|
Hi, I've several apps using DBus and acting as server as well as client. Common pattern: app A registers on DBus signal Sig1 of app B. signal handler (callback) of Sig1 does some work including invoking method x() of app C (via DBus -> dbus_send_with_reply_blocking() or so). The problem is that the apps must be multithreaded too (for responsiveness). I wrote a small test app (echo_server, echo_client) where the client calls echo_serve::request() in 5 threads at the same time. I get sometimes exceptions thrown ("Not enought memory"). It seams to me this error is raised inside dbus (not dbus-cxx). My question is: is dbus-cxx prepared to be used in a multithreaded env where the app actrs a cleint as well server? regards, Oliver #### echo ### #ifndef TEST_ECHO_H #define TEST_ECHO_H #include <string> #include <sigc++/sigc++.h> namespace test { class echo { private: sigc::signal< void, std::string > sig_; public: std::string reply( std::string msg) { return msg; } sigc::signal< void, std::string > signal_event() { return sig_; } void do_emit_event( std::string const& msg) { sig_.emit( msg); } }; } #endif // TEST_ECHO_H ### server #### #include "echo_adapter.h" #include "echo.h" int main() { DBus::init(); int ret; DBus::Dispatcher dispatcher; DBus::Connection::pointer conn = dispatcher.create_connection(DBus::BUS_SYSTEM); // request a name on the bus ret = conn->request_name( "test.echo.server", DBUS_NAME_FLAG_REPLACE_EXISTING); if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) return 1; test::echo handler; test::echoAdapter::pointer adapter = test::echoAdapter::create(&handler); conn->register_object( adapter); std::cout << "Running" << std::flush; for(;;) { std::cout << "." << std::flush; sleep(1); } std::cout << std::endl; return 0; } #### client ##### include <iostream> #include <stdexcept> #include <sstream> #include <string> #include <boost/bind.hpp> #include <boost/ref.hpp> #include <boost/thread.hpp> #include "echo_proxy.h" #include <cstdlib> void request( boost::barrier & b, test::echoProxy::pointer echo, std::string const& msg) { std::stringstream ss; ss << boost::this_thread::get_id(); try { b.wait(); fprintf( stderr, "thread %s: request == %s, reply == %s\n", ss.str().c_str(), msg.c_str(), echo->reply( msg).c_str() ); } catch ( std::exception const& e) { fprintf( stderr, "thread %s: exception catched == %s\n", ss.str().c_str(), e.what() ); ::abort(); } catch (...) { fprintf( stderr, "thread %s: unhandled exception catched\n", ss.str().c_str() ); } } int main(int argc, const char** argv) { try { DBus::init(); DBus::Dispatcher dispatcher; DBus::Connection::pointer connection = dispatcher.create_connection( DBus::BUS_SYSTEM); test::echoProxy::pointer echo = test::echoProxy::create( connection); boost::thread_group tg; boost::barrier b( 5); tg.create_thread( boost::bind( & request, boost::ref( b), echo, "abc") ); tg.create_thread( boost::bind( & request, boost::ref( b), echo, "def") ); tg.create_thread( boost::bind( & request, boost::ref( b), echo, "ghi") ); tg.create_thread( boost::bind( & request, boost::ref( b), echo, "jkl") ); tg.create_thread( boost::bind( & request, boost::ref( b), echo, "mno") ); tg.join_all(); return 0; } catch ( std::exception const& e) { std::cerr << "exception catched: " << e.what() << std::endl; } catch (...) { std::cerr << "unhandled exception catched" << std::endl; } return -1; } |