What happens when there are two main-loops in one process?

Lars Hanisch dvb at flensrocker.de
Sun Apr 14 12:45:26 PDT 2013


Hi,

 I'm working on some plugins for the vdr[1].
 One (dbus2vdr[2]) is for exposing some objects and methods of vdr via dbus, the other one (avahi4vdr[3]) communicates
with the avahi-daemon for publishing some services (like the built-in SVDRP network port and services other plugins offer).

 I experience a segfault sometimes on startup, but even rarely on stopping the vdr process. The plugins are loaded with
dlopen. I'm on Ubuntu 12.04 with all updates. dbus/libdbus is version "1.4.18-1ubuntu1.3", libavahi-client is
"0.6.30-5ubuntu2".


 dbus2vdr is my first project in using DBus and understanding the whole main-loop stuff is a bit complicated. :) So I
put something together, which seems to work.
 This is the "main loop" dbus2vdr uses, started in its own thread:

  dbus_threads_init_default(); // actually called in the main thread
  ...
  // the following runs in an own thread
  dbus_error_init(&_err);
  _conn = dbus_bus_get(DBUS_BUS_SYSTEM, &_err);
  dbus_connection_set_exit_on_disconnect(_conn, false);
  dbus_bus_request_name(_conn, "de.tvdr.vdr", DBUS_NAME_FLAG_REPLACE_EXISTING, &_err);
  ...
  while (thread_is_running) {
    dbus_connection_read_write_dispatch(_conn, 10);
    if (dbus_connection_has_messages_to_send(_conn))
      dbus_connection_flush(_conn);
    DBusMessage *msg = dbus_connection_pop_message(_conn);
    if (msg == NULL) {
      if (!thread_is_running)
        break;
      continue;
      }
    // "other thread" will unref message if it handles it
    if (!handle_message_in_other_thread(_conn, msg))
      dbus_message_unref(msg);
    }
  dbus_connection_unref(_conn);

 This plugin works as expected and handles incoming method calls and sends signals as well.


 Next piece: avahi4vdr.
 I use the "simple poll" main loop of libavahi-client[4], avahi4vdr also calls dbus_threads_init_default() on process
start (on the same main thread as dbus2vdr, so they won't interfere and are called one after the other). But nonetheless
sometimes it crashes with a segfault:

#0  __strcmp_ssse3 () at ../sysdeps/x86_64/multiarch/../strcmp.S:213
#1  0x00007f45df076c5a in filter_func (bus=<optimized out>, message=0x7f45a0001ad0, userdata=0x7f45a00009c0) at client.c:196
#2  0x00007f45df8d5ac6 in dbus_connection_dispatch (connection=0x7f45a00015d0) at ../../dbus/dbus-connection.c:4603
#3  0x00007f45df07ddd6 in dispatch_timeout_callback (t=<optimized out>, userdata=<optimized out>) at
../avahi-common/dbus-watch-glue.c:105
#4  0x00007f45df28a630 in avahi_simple_poll_dispatch (s=0x7f45a00008c0) at simple-watch.c:570
#5  0x00007f45df28a91d in avahi_simple_poll_loop (s=0x7f45a00008c0) at simple-watch.c:646
#6  0x00007f45df497b23 in cAvahiClient::Action (this=0x1b97e80) at avahi-client.c:235
#7  0x000000000050bbcd in cThread::StartThread (Thread=0x1b97e80) at thread.c:262
#8  0x00007f45e1dd8e9a in start_thread (arg=0x7f45beffd700) at pthread_create.c:308
#9  0x00007f45e1b05cbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#10 0x0000000000000000 in ?? ()

 Both plugins connect to the system bus so I think there might be some kind of race condition or other complication
between these two plugins.

 So, here's my question (finally):
 Is this actually "allowed", having too main loops in one process? What is the preferred way if not?
 What happens, if some other plugin author uses some lib with another dbus main loop?

 I haven't worked with glibc (and its main loop) for now, I thought I could come around that... :)
 Any advice for me?


Thanks,
Lars.

[1] http://www.tvdr.de/
[2] https://github.com/flensrocker/vdr-plugin-dbus2vdr
[3] https://github.com/flensrocker/vdr-plugin-avahi4vdr
[4] http://avahi.org/download/doxygen/client-publish-service_8c-example.html


More information about the dbus mailing list