ares_init_options: only propagate init failures from options

Commit 46bb820be3 ("ares_init_options: don't lose init failure")
changed init behaviour so that earlier errors in initialization
weren't lost.  In particular, if the user passes in specific
options but they are not applied (e.g. because of an allocation
failure), that failure needs to be reported back to the user; this
also applies when duplicating a channel with ares_dup().

However, other initialization failures can be ignored and
overridden -- in particular, if init_by_resolv_conf() or
init_by_environment() fail, then falling back to default values
is OK.

So only preserve failures from the init_by_options() stage, not
from all initialization stages.

Fixes issue 60.
pull/20/merge
David Drysdale 8 years ago
parent 220b2b5320
commit 55bbe92677
  1. 30
      ares_init.c
  2. 4
      test/ares-test-init.cc

@ -112,7 +112,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
ares_channel channel;
int i;
int status = ARES_SUCCESS;
int status2;
struct timeval now;
#ifdef CURLDEBUG
@ -190,18 +189,17 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
* precedence to lowest.
*/
if (status == ARES_SUCCESS) {
status = init_by_options(channel, options, optmask);
if (status != ARES_SUCCESS)
DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
ares_strerror(status)));
}
if (status == ARES_SUCCESS) {
status = init_by_environment(channel);
if (status != ARES_SUCCESS)
DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
ares_strerror(status)));
status = init_by_options(channel, options, optmask);
if (status != ARES_SUCCESS) {
DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n",
ares_strerror(status)));
/* If we fail to apply user-specified options, fail the whole init process */
goto done;
}
status = init_by_environment(channel);
if (status != ARES_SUCCESS)
DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n",
ares_strerror(status)));
if (status == ARES_SUCCESS) {
status = init_by_resolv_conf(channel);
if (status != ARES_SUCCESS)
@ -213,13 +211,10 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
* No matter what failed or succeeded, seed defaults to provide
* useful behavior for things that we missed.
*/
status2 = init_by_defaults(channel);
if (status2 != ARES_SUCCESS) {
status = init_by_defaults(channel);
if (status != ARES_SUCCESS)
DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n",
ares_strerror(status)));
if (status == ARES_SUCCESS)
status = status2;
}
/* Generate random key */
@ -232,6 +227,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
ares_strerror(status)));
}
done:
if (status != ARES_SUCCESS)
{
/* Something failed; clean up memory we may have allocated. */

@ -451,8 +451,8 @@ CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable,
"myhostname", "mydomainname.org", filelist) {
ares_channel channel = nullptr;
MakeUnreadable hide("/etc/resolv.conf");
// Unavailable /etc/resolv.conf fails initialization.
EXPECT_EQ(ARES_EFILE, ares_init(&channel));
// Unavailable /etc/resolv.conf falls back to defaults
EXPECT_EQ(ARES_SUCCESS, ares_init(&channel));
return HasFailure();
}
CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable,

Loading…
Cancel
Save