Discussion:
sd_bus_get_unique_name returns -EBADMSG or -EBUSY
(too old to reply)
Carlo Wood
2021-04-01 11:32:19 UTC
Permalink
I am getting all kinds of unlisted errors from
sd_bus_get_unique_name.

EBADMSG and EBUSY are not listed on the manual page of
sd_bus_get_unique_name.

What is the cause of these errors, and how should I deal with
them?

Carlo Wood
Lennart Poettering
2021-04-06 16:41:21 UTC
Permalink
Post by Carlo Wood
I am getting all kinds of unlisted errors from
sd_bus_get_unique_name.
EBADMSG and EBUSY are not listed on the manual page of
sd_bus_get_unique_name.
We only document prominent errors directly, but the list is by no
means complete.
Post by Carlo Wood
What is the cause of these errors, and how should I deal with
them?
I don#t know. Provide a minimal reproducer?

EBADMSG usually means that somehow an invalid dbus packet we couldn't
parse entered the stream. maybe some memory corruption thing? or maybe
you are using this in a threaded env without locking?

Lennart

--
Lennart Poettering, Berlin
Carlo Wood
2021-04-07 10:17:57 UTC
Permalink
On Tue, 6 Apr 2021 18:41:21 +0200
Post by Lennart Poettering
EBADMSG usually means that somehow an invalid dbus packet we couldn't
parse entered the stream. maybe some memory corruption thing? or maybe
you are using this in a threaded env without locking?
Lennart
Yes, that is the case. I was reading up on the demands,
which I found on
https://www.spinics.net/lists/systemd-devel/msg01779.html

making me wonder why I went through the trouble of supporting
dbus with my library :p (which aims at massive parallel
execution without EVER blocking or going to sleep).

Libraries that do not support threading are a pain :/.

It would really help if you could tell me a more fine-
grained multi-threading demands; like - per connection.

Surely I can execute sd_bus_* functions that deal with
a different dbus* in parallel?

As you stated in the linked email, there is no global state.
So, I suppose that if I call any sd_bus_* function that
all that I have to take into account is that the data
that is passed to those functions is protected. If they
use different connections, then no data should be shared,
no?

Carlo
Lennart Poettering
2021-04-07 14:15:40 UTC
Permalink
Post by Carlo Wood
On Tue, 6 Apr 2021 18:41:21 +0200
Post by Lennart Poettering
EBADMSG usually means that somehow an invalid dbus packet we couldn't
parse entered the stream. maybe some memory corruption thing? or maybe
you are using this in a threaded env without locking?
Lennart
Yes, that is the case. I was reading up on the demands,
which I found on
https://www.spinics.net/lists/systemd-devel/msg01779.html
making me wonder why I went through the trouble of supporting
dbus with my library :p (which aims at massive parallel
execution without EVER blocking or going to sleep).
sd-bus is fully async. It only blocks if you call the functions that
are synchronous wrappers around async functions. e.g. sd_bus_call() is
actually more or less a synchronous wrapper around the same stuff that
sd_bus_call_async() does async.

Async means here the work is enqueued into the socket or client side,
and then dispatched by an event loop of sorts. The event loop can be
sd-event, or you can use any other you like, that has a poll()-like
glue interface.

You are supposed to have one sd-bus connection per thread though. It's
the model this is all built for. If you want to share one connection
among multiple threads, you need to do your locking around that
yourself.
Post by Carlo Wood
Libraries that do not support threading are a pain :/.
Well, depends what you mean by "supporting". sd-bus is written with
threads in mind, i.e. everything is broken down to local contexts,
there's no global non-fixed data and such. It's just a different model
that you might be used to: i.e. one connection per thread and locking
if desired must be done in your own code.
Post by Carlo Wood
It would really help if you could tell me a more fine-
grained multi-threading demands; like - per connection.
D-Bus as a protocol is big on global ordering. It's thus not really
compatible with being dispatched in thread pools, because those would
basically randomize dispatch ordering.

It's a design decision of D-Bus.
Post by Carlo Wood
Surely I can execute sd_bus_* functions that deal with
a different dbus* in parallel?
Yes. You are not supposed to share individual sd_bus objects (and
their associated helper objects) between multiple threads, unless you
do your own locking around it. But you can have as many sd_bus objects
you want and run the independently from any number of threads you
like, fully in parallel.
Post by Carlo Wood
As you stated in the linked email, there is no global state.
So, I suppose that if I call any sd_bus_* function that
all that I have to take into account is that the data
that is passed to those functions is protected. If they
use different connections, then no data should be shared,
no?
Not sure I grok the question.

Lennart

--
Lennart Poettering, Berlin
Carlo Wood
2021-04-07 15:20:52 UTC
Permalink
On Wed, 7 Apr 2021 16:15:40 +0200
Post by Lennart Poettering
Post by Carlo Wood
As you stated in the linked email, there is no global state.
So, I suppose that if I call any sd_bus_* function that
all that I have to take into account is that the data
that is passed to those functions is protected. If they
use different connections, then no data should be shared,
no?
Not sure I grok the question.
It was just a repeat, stated differently.

I assume that anything related to the same sd_bus* object,
which includes sd_bus_message* objects that use that sd_bus*
can not be passed to more than one function at a time and
executed in parallel. But (which is what I stated above)
if the (associated) sd_bus* is different, then that is possible.

I think you already confirmed that this is possible.

So, my plan will be to add a "lock" per connection.

I have dbus::Connection objects and it will be very clear
which one any call to a sd_bus_* function is associated
with; so I can use those objects as "lock". I put lock between
quotes here because it won't be an ordinary mutex: a mutex
blocks other threads as long as the thread holds this mutex
(aka, is inside the function). That is quite long imho:
normally I try to keep mutexes that can block out other threads
for (much) less than a micro second. Longer than 10 micro
seconds is unacceptable (and wrong use of mutexes imho).

I invented a different concept to deal with threads with
my library: I run threaded code in 'tasks' which are then
basically executed single-threaded (not the same thread,
but one thread at a time runs a task). All variables that
a task deals with while running are private members of
the task object and there is therefore no locking needed
at all for those variables.

However, I decided against using a different sdbus connection
per thread for the simple reason that I do not keep track
of threads; I have tasks that when needing to run get cpu
time from an available thread. I could use one connection
per task, but that has (a lot of) overhead, since I create,
execute and destroy tasks a LOT. Aka, you'd get a new
connection for every sd_bus message. It seemed more logical
to me to make a connection and keep that alive; and reuse
it over and over for new messages. That way, in most cases,
I'll just have a single connection (ie, to the userbus)
without a repeat of the handshake all the time.

But since I have tasks for doing everything, like sending
a signal, or a method call, and those run in parallel at
the moment, the connection, aka sd_bus object, is used
by multiple threads concurrently at the moment, causing
more than one thread to enter the sd_bus library at the
time time for the same sd_bus object.

Loading...