Multithreaded DBus using glib quirkyness
Richard Reich
rreich@rdrtech.com
19 Jun 2003 09:21:46 -0400
--=-My7Y0U+vjg6b3ZZAWx6+
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hello,
Being new to dbus, I hope I'm not making some mistakes here...
I'm experiencing some "weirdness" when I try to use threads with dbus.
I'm using the glib extensions in my glibmm application. I ran across
one bug in the header that mitr on irc.freenode.net/#dbus was able to
help me with, basically needing G_BEGIN_DECLS/G_END_DECLS in the header
dbus-glib.h.
After getting past this hurdle I've begun testing if dbus can accept the
load I'm going to be putting on it. Max of 7500 msgs/sec, one server
serving up those messages and any number of clients, currently 10.
So I coded up a quick c++ glibmm app that created a few threads that
listened for the broadcast messages sent by dbus-send.
If I have 1 thread or just the main thread listening all is well. If I
have more I get random "Illegal Operations" or segfaults. I tried using
dbus_gthread_init(), but this caused my app to not recieve anything from
the dbus system.
So my question is, am I doing anything wrong?
Attached you should find the c++ file used to demonstrate this.
To send a message I use, from the web site,
dbus-send --dest='org.freedesktop.ExampleService' \
org.freedesktop.ExampleMessage \
int32:47 string:'hello world' double:65.32
Though for some reason dbus-monitor nor my app get any of the data.
I'm using gcc 3.2.2
to compile the file I use this line.
g++ main.cpp `pkg-config dbus-glib-1 dbus-1 gthread-2.0 glibmm-2.0
--cflags --libs`
Thanks
Richard Reich
--=-My7Y0U+vjg6b3ZZAWx6+
Content-Disposition: attachment; filename=main.cpp
Content-Type: text/x-c++; name=main.cpp; charset=ANSI_X3.4-1968
Content-Transfer-Encoding: 7bit
#include <unistd.h>
#include <sys/time.h>
#include <iostream>
#include <glibmm.h>
#define DBUS_API_SUBJECT_TO_CHANGE 1
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
using namespace std;
using namespace SigC;
using namespace Glib;
// copied from dbus-monitor.c
static DBusHandlerResult
handler_func (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
printf("Hello World\n");
cout << "Got it! PID: " << getpid() << endl;
//*
DBusMessageIter iter;
printf ("message name=%s; sender=%s\n", dbus_message_get_name (message),
dbus_message_get_sender (message));
dbus_message_iter_init (message, &iter);
do
{
int type = dbus_message_iter_get_arg_type (&iter);
char *str;
dbus_uint32_t uint32;
dbus_int32_t int32;
double d;
unsigned char byte;
if (type == DBUS_TYPE_INVALID)
break;
switch (type)
{
case DBUS_TYPE_STRING:
str = dbus_message_iter_get_string (&iter);
printf ("string:%s\n", str);
break;
case DBUS_TYPE_INT32:
int32 = dbus_message_iter_get_int32 (&iter);
printf ("int32:%d\n", int32);
break;
case DBUS_TYPE_UINT32:
uint32 = dbus_message_iter_get_uint32 (&iter);
printf ("int32:%u\n", uint32);
break;
case DBUS_TYPE_DOUBLE:
d = dbus_message_iter_get_double (&iter);
printf ("double:%f\n", d);
break;
case DBUS_TYPE_BYTE:
byte = dbus_message_iter_get_byte (&iter);
printf ("byte:%d\n", byte);
break;
default:
printf ("(unknown arg type %d)\n", type);
break;
}
} while (dbus_message_iter_next (&iter));
// */
return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}
void my_thread ( void )
{
cout << "New thread " << getpid() << endl;
Glib::RefPtr<MainContext> cont = MainContext::create();
Glib::RefPtr<MainLoop> loop = MainLoop::create(cont);
// Copied from dbus-monitor.c
///////////////////////////////////////////////////////////////////////////////
DBusConnection *connection;
DBusError error;
DBusBusType type = DBUS_BUS_SYSTEM;
DBusMessageHandler *handler;
dbus_error_init (&error);
connection = dbus_bus_get (type, &error);
if (connection == NULL)
{
fprintf (stderr, "Failed to open connection to %s message bus: %s\n",
(type == DBUS_BUS_SYSTEM) ? "system" : "session",
error.message);
dbus_error_free (&error);
exit (1);
}
dbus_connection_setup_with_g_main (connection, cont->gobj());
handler = dbus_message_handler_new (handler_func, NULL, NULL);
dbus_connection_add_filter (connection, handler);
///////////////////////////////////////////////////////////////////////////////
loop->run();
cout << "Ending" << endl;
}
int main(int argc, char *argv[])
{
Glib::thread_init();
// Comment this out and messages begin to be recieved.
dbus_gthread_init();
Glib::Dispatcher sync;
Glib::RefPtr<MainLoop> main = MainLoop::create();
// simulate 10 clients listening
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
Glib::Thread::create(slot(my_thread), false);
///////////////////////////////////////////////////////////////////////////////
/*
DBusConnection *connection;
DBusError error;
DBusBusType type = DBUS_BUS_SYSTEM;
DBusMessageHandler *handler;
dbus_error_init (&error);
connection = dbus_bus_get (type, &error);
if (connection == NULL)
{
fprintf (stderr, "Failed to open connection to %s message bus: %s\n",
(type == DBUS_BUS_SYSTEM) ? "system" : "session",
error.message);
dbus_error_free (&error);
exit (1);
}
dbus_connection_setup_with_g_main (connection, NULL);
handler = dbus_message_handler_new (handler_func, NULL, NULL);
dbus_connection_add_filter (connection, handler);
// */
///////////////////////////////////////////////////////////////////////////////
main->run();
return 0;
}
--=-My7Y0U+vjg6b3ZZAWx6+--