Synchronous method in asynchronous signal callback

Thomas Downing tdowning at bomgar.com
Thu May 14 09:54:23 PDT 2015


Simon has given some good advice, to which I add, a great rule for working 
with libdbus is _never_ make any calls to libdbus from any thread if 
dbus_connection_dispatch is in the call stack of any thread.

Like any rule there are exceptions, such as dbus_message_ref and _unref.

With this, using the asynchronous dbus_connection_send pretty straight 
forward.  Switching to the asynchronous send of method calls shouldn't be that 
hard, you have an event loop no?

So, pseudo code _might_ look like:

main_loop
	epoll_wait on dbus_watches and my_event
	if dbus_watch
		do dispatch
	if my event
		if receive_queue has messages
			for each message
				invoke_method( messages )
		if send_queue has messages
			for each message
				send message

filter_func
	if is signal A or reply to my method call
		dbus_message_ref signal
		push onto receive queue
		write my_event

invoke_method
	if signal A
		push my_method_call onto send_queue
		write my_event
	if reply to my method call
		use_reply
	dbus_message_unref signal or reply
		


On Thursday, May 14, 2015 10:16:05 Marco Bascetta wrote:
> Hello,
> 
> I'm using libdbus with a poll mainloop. I monitor the DBusWatch file
> descriptor to call "dbus_watch_handle" and "dbus_connection_dispatch".
> Also, I add a connection filter to handle asynchronous signals (only
> DBUS_MESSAGE_TYPE_SIGNAL messages).
> 
> When an event occurs, a callback is called and a specified method is
> performed throught "dbus_connection_send_with_reply_and_block" and a
> flag is set in order to indicates that the dispatch function must run
> another time.
> 
> This is an example of the code
> [pseudocode]
> init_func()
> {
>      dbus_threads_init_default()
>      conn = dbus_bus_get(...)
>      dbus_connection_set_watch_functions(conn, ...)               # This
> store watch_fd in poll
>      dbus_connection_add_filter(conn, filter_func, ...)
> }
> 
> invoke_method()
> {
>      dbus_connection_send_with_reply_and_block(conn, ...)
>      use_reply()
>      flag_set(force_dispatch)
> }
> 
> filter_func()
> {
>      if( dbus_message_get_type(...) == DBUS_MESSAGE_TYPE_SIGNAL ) {
>          if( is(signal_A) ) {
>              invoke_method()
>          } else {
>              do_other_things()
>          }
>      }
> }
> 
> # This is called when watch_fd
> dispach_func()
> {
>          do {
>              flag_unset(force_dispatch)
> 
>              dbus_watch_handle(dbus_watch,
> dbus_watch_get_flags(dbus_watch));
> 
>              while (dbus_connection_get_dispatch_status(conn) ==
> DBUS_DISPATCH_DATA_REMAINS) {
>                  dbus_connection_dispatch(conn);
>              }
> 
>          } while( flag_is_set(force_dispatch) );
> }
> [pseudocode]
> 
> It works without deadlock or message missing, but the signals received
> during the "invoke_method" are delayed until another signal is received
> (watch fd unlocks the poll) (and this could occurs much later...)
> 
> Could you suggest me how to resolve this issue without using the
> asynchronous calls only?
> 
> Thanks
> 
> Best regards


More information about the dbus mailing list