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