summaryrefslogtreecommitdiff
path: root/dbus/dbus-sysdeps.c
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2018-03-08 14:27:36 +0000
committerSimon McVittie <smcv@collabora.com>2018-03-09 12:28:27 +0000
commitff359872b9ac5fe952c9f0d9e6cf116630d77cd3 (patch)
tree2e8c046990276fd4f704bb858da3d69842d37cbc /dbus/dbus-sysdeps.c
parente894c94562af3e9a340a3fa931f499b827171e24 (diff)
downloaddbus-ff359872b9ac5fe952c9f0d9e6cf116630d77cd3.tar.gz
sysdeps-unix: Treat bind() failures as non-fatal
When we use AF_UNSPEC, we are likely to get multiple addresses back from getaddrinfo(), and perhaps we won't be able to use them all. Give that failure mode, or any other bind() failure, the same treatment as EADDRINUSE failures here and all connect() failures in _dbus_connect_tcp_socket_with_nonce(): if any address succeeds, then the overall operation succeeds, but if all of them fail, then the overall operation fails. I've made _dbus_combine_tcp_errors() generic enough that _dbus_connect_tcp_socket_with_nonce() could use it too, although that isn't implemented here. Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de> [smcv: Adjust commit message] Signed-off-by: Simon McVittie <smcv@collabora.com> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=61922
Diffstat (limited to 'dbus/dbus-sysdeps.c')
-rw-r--r--dbus/dbus-sysdeps.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 43fa109f..98d5a925 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -908,6 +908,74 @@ _dbus_set_error_with_inet_sockaddr (DBusError *error,
}
}
+void
+_dbus_combine_tcp_errors (DBusList **sources,
+ const char *summary,
+ const char *host,
+ const char *port,
+ DBusError *dest)
+{
+ DBusString message = _DBUS_STRING_INIT_INVALID;
+
+ if (_dbus_list_length_is_one (sources))
+ {
+ /* If there was exactly one error, just use it */
+ dbus_move_error (_dbus_list_get_first (sources), dest);
+ }
+ else
+ {
+ DBusList *iter;
+ const char *name;
+
+ /* If there was more than one error, concatenate all the
+ * errors' diagnostic messages, and use their common error
+ * name, or DBUS_ERROR_FAILED if more than one name is
+ * represented */
+ if (!_dbus_string_init (&message))
+ {
+ _DBUS_SET_OOM (dest);
+ goto out;
+ }
+
+ for (iter = _dbus_list_get_first_link (sources);
+ iter != NULL;
+ iter = _dbus_list_get_next_link (sources, iter))
+ {
+ DBusError *error = iter->data;
+
+ if (name == NULL)
+ {
+ /* no error names known yet, try to use this one */
+ name = error->name;
+ }
+ else if (strcmp (name, error->name) != 0)
+ {
+ /* errors of two different names exist, reconcile by
+ * using FAILED */
+ name = DBUS_ERROR_FAILED;
+ }
+
+ if ((_dbus_string_get_length (&message) > 0 &&
+ !_dbus_string_append (&message, "; ")) ||
+ !_dbus_string_append (&message, error->message))
+ {
+ _DBUS_SET_OOM (dest);
+ goto out;
+ }
+ }
+
+ if (name == NULL)
+ name = DBUS_ERROR_FAILED;
+
+ dbus_set_error (dest, name, "%s to \"%s\":%s (%s)",
+ summary, host ? host : "*", port,
+ _dbus_string_get_const_data (&message));
+ }
+
+out:
+ _dbus_string_free (&message);
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */