summaryrefslogtreecommitdiff
path: root/src/nm-connectivity.h
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-01-05 17:46:49 +0100
committerThomas Haller <thaller@redhat.com>2018-04-10 15:11:23 +0200
commitd8a31794c8b9db243076ba0c24dfe6e496b78697 (patch)
treebdc2426e90fa820cd777120cb3a86614904c3e20 /src/nm-connectivity.h
parent4417b8bf3eef8ca7cf45dc973ab107249bd10d67 (diff)
downloadNetworkManager-d8a31794c8b9db243076ba0c24dfe6e496b78697.tar.gz
connectivity: rework async connectivity check requests
An asynchronous request should either be cancellable or not keep the target object alive. Preferably both. Otherwise, it is impossible to do a controlled shutdown when terminating NetworkManager. Currently, when NetworkManager is about to terminate, it just quits the mainloop and essentially leaks everything. That is a bug. If we ever want to fix that, every asynchronous request must be cancellable in a controlled way (or it must not prevent objects from getting disposed, where disposing the object automatically cancels the callback). Rework the asynchronous request for connectivity check to - return a handle that can be used to cancel the operation. Cancelling is optional. The caller may choose to ignore the handle because the asynchronous operation does not keep the target object alive. That means, it is still possible to shutdown, by everybody giving up their reference to the target object. In which case the callback will be invoked during dispose() of the target object. - also, the callback will always be invoked exactly once, and never synchronously from within the asynchronous start call. But during cancel(), the callback is invoked synchronously from within cancel(). Note that it's only allowed to cancel an action at most once, and never after the callback is invoked (also not from within the callback itself). - also, NMConnectivity already supports a fake handler, in case connectivity check is disabled via configuration. Hence, reuse the same code paths also when compiling without --enable-concheck. That means, instead of having #if WITH_CONCHECK at various callers, move them into NMConnectivity. The downside is, that if you build without concheck, there is a small overhead compared to before. The upside is, we reuse the same code paths when compiling with or without concheck. - also, the patch synchronizes the connecitivty states. For example, previously `nmcli networking connectivity check` would schedule requests in parallel, and return the accumulated result of the individual requests. However, the global connectivity state of the manager might have have been the same as the answer to the explicit connecitivity check, because while the answer for the manual check is waiting for all pending checks to complete, the global connectivity state could already change. That is just wrong. There are not multiple global connectivity states at the same time, there is just one. A manual connectivity check should have the meaning of ensure that the global state is up to date, but it still should return the global connectivity state -- not the answers for several connectivity checks issued in parallel. This is related to commit b799de281bc01073c31dd2c86171b29c8132441c (libnm: update property in the manager after connectivity check), which tries to address a similar problem client side. Similarly, each device has a connectivity state. While there might be several connectivity checks per device pending, whenever a check completes, it can update the per-device state (and return that device state as result), but the immediate answer of the individual check might not matter. This is especially the case, when a later request returns earlier and obsoletes all earlier requests. In that case, earlier requests return with the result of the currend devices connectivity state. This patch cleans up the internal API and gives a better defined behavior to the user (thus, the simple API which simplifies implementation for the caller). However, the implementation of getting this API right and properly handle cancel and destruction of the target object is more complicated and complex. But this but is not just for the sake of a nicer API. This fixes actual issues explained above. Also, get rid of GAsyncResult to track information about the pending request. Instead, allocate our own handle structure, which ends up to be nicer because it's strongly typed and has exactly the properties that are useful to track the request. Also, it gets rid of the awkward _finish() API by passing the relevant arguments to the callback directly.
Diffstat (limited to 'src/nm-connectivity.h')
-rw-r--r--src/nm-connectivity.h25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h
index d9a9f2338b..6c16982307 100644
--- a/src/nm-connectivity.h
+++ b/src/nm-connectivity.h
@@ -24,6 +24,9 @@
#include "nm-dbus-interface.h"
+#define NM_CONNECTIVITY_ERROR ((NMConnectivityState) -1)
+#define NM_CONNECTIVITY_FAKE ((NMConnectivityState) -2)
+
#define NM_TYPE_CONNECTIVITY (nm_connectivity_get_type ())
#define NM_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTIVITY, NMConnectivity))
#define NM_CONNECTIVITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONNECTIVITY, NMConnectivityClass))
@@ -41,13 +44,21 @@ NMConnectivity *nm_connectivity_get (void);
const char *nm_connectivity_state_to_string (NMConnectivityState state);
-void nm_connectivity_check_async (NMConnectivity *self,
- const char *iface,
- GAsyncReadyCallback callback,
- gpointer user_data);
-NMConnectivityState nm_connectivity_check_finish (NMConnectivity *self,
- GAsyncResult *result,
- GError **error);
gboolean nm_connectivity_check_enabled (NMConnectivity *self);
+typedef struct _NMConnectivityCheckHandle NMConnectivityCheckHandle;
+
+typedef void (*NMConnectivityCheckCallback) (NMConnectivity *self,
+ NMConnectivityCheckHandle *handle,
+ NMConnectivityState state,
+ GError *error,
+ gpointer user_data);
+
+NMConnectivityCheckHandle *nm_connectivity_check_start (NMConnectivity *self,
+ const char *iface,
+ NMConnectivityCheckCallback callback,
+ gpointer user_data);
+
+void nm_connectivity_check_cancel (NMConnectivityCheckHandle *handle);
+
#endif /* __NETWORKMANAGER_CONNECTIVITY_H__ */