Subject: Re: improving ABI "survival rate"

Re: improving ABI "survival rate"

From: Yang Tse <yangsita_at_gmail.com>
Date: Fri, 28 Nov 2008 02:46:51 +0100

2008/11/27, Daniel Stenberg wrote:

> The biggest change would be to simply not expose the struct and
> introduce a ares_setopt() style function for setting specific options
> [...]
> I still like this approach since it makes things more stable and thus
> I'm interested in how c-ares users would like it.
>
> In fact, it struck me just now that we can in fact introduce ares_setopt()
> right now and move the 'rotate' and the new 'ipv6servers' to get set by this
> new function only, and then we'd remain ABI compatible with the previous
> release and still start moving towards this new approach!

Let's suppose that in order to not break ABI, a new function
ares_setopt() is introduced, and obviously the ares_options struct is
kept in the public interface unchanged from last release, as well as
ares_init_options(), ares_save_options() and ares_destroy_options().

Some considerations/questions...

The introduction of a new public function somehow breaks API and ABI.
'People' are fond of saying that there is no need to make a SO bump
when this is done. But actually it should be done. A program which
counts on the existence of the new function will fail when faced with
a shared library with the same SO number but which actually is a
previous binary version in which the new function didn't exist yet. I
won't argue this further, I just wanted to mention my personal opinion
on what I think is a wrong-doing but quite common practice.

Ok, I close my eyes and assume for the rest of the message that the
introduction of the new public ares_setopt() does not break API nor
ABI nor requires an SO bump.

Now, let's imagine that someone has used ares_setopt() to setup a
couple of IPv6 nameservers. This information cannot be stored in a
variable of the existing ares_options struct, so somehow it will be
kept 'somewhere' before doing some sort of, some other new public
functions, ares_init_channel_with_newstyle_opts(), and even
ares_destroy_newstyle_opts().

Now the user, or the library internally, decides it wants to
initialize another ares_channel with the same options as one that
already exists. If he/it uses the old ares_save_options() the newstyle
options won't be copied so a ares_save_newstyle_options() is required.

We have duplicated all the external functions which had an
ares_options struct argument, and also introduced ares_setopt(). Not
to mention the increased complexity that the library internals will
suffer.

Let's suppose that such a setup is released. When will we be able to
get rid of the external ares_options struct (which was one of the
goals of all this change)? I presume that never as it would be an
API/ABI breakage. And we will have to live with the duplicate/separate
options and internal complexity forever long. And people wondering why
there are duplicate functions to handle the options stuff.

I really hope that what you have in mind is something much more clever
than the scenario I've described above which is a nightmare for which
I'm really against. I think that that the duplicate mess is not worth
the 'theoretical' ABI compatibility.

Can we really eat and have the cake at the same time without having two cakes?

-- 
-=[Yang]=-
Received on 2008-11-28