Coccinelle:
@@
expression a, b;
@@
-a ? a : b
+a ?: b
Applied with:
spatch --sp-file ternary.cocci --in-place --smpl-spacing --dir .
With some manual adjustments on spots that Cocci didn't catch for
reasons unknown.
Thanks to the marvelous effort of the GNU compiler developer we can now
spare a couple of bits that could be used for more important things,
like this commit message. Standards commitees yet have to catch up.
The libnm API fir checkpoints was only introduced with 1.11. It
is not yet stable, so there is still time to adjust it. Note that
this changes API/ABI of the development branch.
Changes:
- we only add async variants of the checkpoint functions. I believe
that synchronous D-Bus methods are fundamentally flawed, because
they mess up the ordering of events.
Rename the async functions by removing the "_async" suffix. This
matches glib style, for which the async form is also not specially
marked.
- for function that refere to a particular checkpoint (rollback and
destroy), accept the D-Bus path as string, instead of an NMCheckpoint
instance. This form is more flexible, because it allows to use
the function without having a NMCheckpoint instance at hand. On the
other hand, if one has a NMCheckpoint instance, he can trivially
obtain the path to make the call.
This allows to adjust the timeout of an existing checkpoint.
The main usecase of checkpoints, is to have a fail-safe when
configuring the network remotely. By allowing to reset the timeout,
the user can perform a series of actions, and keep bumping the
timeout. That way, the entire series is still guarded by the same
checkpoint, but the user can start with short timeout, and
re-adjust the timeout as he goes along.
The libnm API only implements the async form (at least for now).
Sync methods are fundamentally wrong with D-Bus, and it's probably
not needed. Also, follow glib convenction, where the async form
doesn't have the _async name suffix. Also, accept a D-Bus path
as argument, not a NMCheckpoint instance. The libnm API should
not be more restricted than the underlying D-Bus API. It would
be cumbersome to require the user to lookup the NMCheckpoint
instance first, especially since libnm doesn't provide an efficient
or convenient lookup-by-path method. On the other hand, retrieving
the path from a NMCheckpoint instance is always possible.
Now that the D-Bus signals in server are reordered, creating
a checkpoint in libnm crashes:
$ examples/python/gi/checkpoint.py create 4
#0 0x00007ffff6d011ee in __strcmp_sse2_unaligned () at /lib64/libc.so.6
#1 0x00007fffeb611c90 in find_checkpoint_info (manager=manager@entry=0x5555559e5110 [NMManager], path=0x7fffdc0092f0 "/org/freedesktop/NetworkManager/Checkpoint/6")
at libnm/nm-manager.c:153
#2 0x00007fffeb611d8f in checkpoint_added (manager=0x5555559e5110 [NMManager], checkpoint=checkpoint@entry=0x555555a122d0 [NMCheckpoint]) at libnm/nm-manager.c:1194
#3 0x00007fffef7db929 in g_cclosure_marshal_VOID__OBJECTv (closure=0x5555559e4b30, return_value=<optimized out>, instance=<optimized out>, args=<optimized out>, marshal_data=<optimized out>, n_params=<optimized out>, param_types=0x5555559e2fc0) at gmarshal.c:2102
#4 0x00007fffef7d8976 in _g_closure_invoke_va (closure=0x5555559e4b30, return_value=0x0, instance=0x5555559e5110, args=0x7fffffffc1c8, n_params=1, param_types=0x5555559e2fc0)
at gclosure.c:867
#5 0x00007fffef7f3ff4 in g_signal_emit_valist (instance=instance@entry=0x5555559e5110, signal_id=signal_id@entry=97, detail=0, var_args=var_args@entry=0x7fffffffc1c8) at gsignal.c:3300
#6 0x00007fffef7f4b48 in g_signal_emit_by_name (instance=instance@entry=0x5555559e5110, detailed_signal=detailed_signal@entry=0x7fffffffc310 "checkpoint-added") at gsignal.c:3487
#7 0x00007fffeb6156d1 in deferred_notify_cb (data=0x5555559e5110) at libnm/nm-object.c:219
#8 0x00007fffeb615ae7 in object_property_maybe_complete (self=0x5555559e5110 [NMManager]) at libnm/nm-object.c:555
#9 0x00007fffeb615e5d in object_created (obj=<optimized out>, path=<optimized out>, user_data=<optimized out>) at libnm/nm-object.c:576
#10 0x00007fffeb61648b in handle_object_array_property (pi=<optimized out>, value=0x7fffdc075070, property_name=0x7fffeb67f117 "checkpoints", self=0x5555559e5110 [NMManager])
at libnm/nm-object.c:671
#11 0x00007fffeb61648b in handle_property_changed (self=self@entry=0x5555559e5110 [NMManager], dbus_name=<optimized out>, value=<optimized out>) at libnm/nm-object.c:740
#12 0x00007fffeb6166e9 in properties_changed (proxy=<optimized out>, changed_properties=<optimized out>, invalidated_properties=<optimized out>, user_data=0x5555559e5110)
at libnm/nm-object.c:772
...
That is, because NetworkManager now first emits signals that the checkpoint
object was created, before answering the D-Bus request. That makes more
sense, but leads to this crash.
The ugliness of how libnm handles object visibility is considerable.
libnm hides objects until they are fully initialized. So, when
the async create-checkpoint operation returns, the object might not
yet be ready to be exposed. We need to delay the result. It would be
better if the API would simply return the created path.
If an operation is cancelled through the GCancellable, then the idiom is
that the operation is always cancelled, even if it has finished
successfully. To ensure this is the case, add calls to
g_simple_async_result_set_check_cancellable everywhere.
Without this, e.g. gnome-control-center will crash when switching away
from the power panel quickly, as the NMClient creation finishes
asynchronously and g-c-c assume that G_IO_ERROR_CANCELLED is returned to
ensure it doesn't access the now invalid user_data parameter.
https://bugzilla.gnome.org/show_bug.cgi?id=794088
We also do this for libnm and libnm-core, where it causes visible changes
in behavior. But if somebody would rely on the hashing implementation
for hash tables, it would be seriously flawed.
We also do this for libnm, where it causes visible changes
in behavior. But if somebody would rely on the hashing implementation
for hash tables, it would be seriously flawed.
GHashTable optimizes a NULL equality function to use direct pointer
comparison. That saves the overhead of calling g_direct_equal().
This is also documented behavior for g_hash_table_new().
While at it, also don't pass g_direct_hash() but use the default
of %NULL. The behavior is the same, but consistently don't use
g_direct_hash().
Currently, after a client performs a connectivity check it cannot
access the up-to-date value of the manager.connectivity property right
away, but it must wait that the queued PropertiesChanged signal is
processed, which is cumbersome.
Arguably, clients already receive the new connectivity value as the
result of the connectivity check call, so they don't have to read it
from the object; however it would be better if the right value of the
object property was available immediately as well.
https://bugzilla.gnome.org/show_bug.cgi?id=784629
This makes it easier to install the files with proper names.
Also, it makes the makefile rules slightly simpler.
Lastly, the documentation is now generated into docs/api, which makes it
possible to get rid of the awkward relative file names in docbook.
The GetPermissions call is very expensive (~400ms here, an extra
NM->polkit call for every known permission while polkit being really
slow to answer) yet seldom needed.
There's no methods to access the permissions -- they're only
communicated via signals.
Unfortunately, we don't know when a signal is hooked, so we still need
to kick of the call. Nevertheless, we don't need to wait for it to
finish.
This speeds up the initial object tree load significantly. Also, it
reduces the object management complexity by shifting the duties to
GDBusObjectManager.
The lifetime of all NMObjects is now managed by the NMClient via the
object manager. The NMClient creates the NMObjects for GDBus objects,
triggers the initialization and serves as an object registry (replaces
the nm-cache).
The ObjectManager uses the o.fd.DBus.ObjectManager API to learn of the
object creation, removal and property changes. It takes care of the
property changes so that we don't have to and lets us always see a
consistent object state. Thus at the time we learn of a new object we
already know its properties.
The NMObject unfortunately can't be made synchronously initializable as
the NMRemoteConnection's settings are not managed with standard
o.fd.DBus Properties and ObjectManager APIs and thus are not known to
the ObjectManager. Thus most of the asynchronous object property
changing code in nm-object.c is preserved. The objects notify the
properties that reference them of their initialization in from their
init_finish() methods, thus the asynchronously created objects are not
allowed to fail creation (or the dependees would wait forever). Not a
problem -- if a connection can't get its Settings, it's either invisible
or being removed (presumably we'd learn of the removal from the object
manager soon).
The NMObjects can't be created by the object manager itself, since we
can't determine the resulting object type in proxy_type() yet (we can't
tell from the name and can't access the interface list). Therefore the
GDBusObject is coupled with a NMObject later on.
Lastly, now that all the objects are managed by the object manager, the
NMRemoteSettings and NMManager go away when the daemon is stopped. The
complexity of dealing with calls to NMClient that would require any of
the resources that these objects manage (connection or device lists,
etc.) had to be moved to NMClient. The bright side is that his allows
for removal all of the daemon presence tracking from NMObject.
On D-Bus level, string (s) or object paths (o) cannot be NULL.
Thus, whenver server exposes such an object, it gets automatically
coerced to "" or "/", respectively.
On client side, libnm should coerce certain properties back, for which
"" is just not a sensible value.
For example, an empty NM_DEVICE_ETHERNET_HW_ADDRESS should be instead
exposed as NULL.
Technically, this is an API change. However, all users were well advised
to expect both NULL and "" as possible return values and handle them
accordingly.
We connect signal handlers to devices when they appear, but don't
disconnect the handlers when the manager instance is destroyed. This
can cause crashes as device_ac_changed() is called on an invalid
manager instance.
Disconnect the handlers from dispose().
https://bugzilla.redhat.com/show_bug.cgi?id=1383758
Add new Reload D-Bus command to reload NetworkManager configuration.
For now, this is like sending SIGHUP to the process. There are several
advantages here:
- it is guarded via PolicyKit authentication while signals
can only be sent by root.
- the user can wait for the reload to be complete instead of sending
an asynchronous signal. For now, we operation completes after
nm_config_reload() returns, but later we could delay the response
further until specific parts are fully reloaded.
- SIGHUP reloads everything including re-reading configuration from
disk while SIGUSR1 reloads just certain parts such as writing out DNS
configuration anew.
Now, the Reload command has a flags argument which is more granular
in selecting parts which are to be reloaded. For example, via
signals the user can:
1) send SIGUSR1: this writes out the DNS configuration to
resolv.conf and possibly reloads other parts without
re-reading configuration and without restarting the DNS plugin.
2) send SIGHUP: this reloads configuration from disk,
writes out resolv.conf and restarts the DNS plugin.
There is no way, to only restart the DNS plugin without also reloading
everything else.
- All internal source files (except "examples", which are not internal)
should include "config.h" first. As also all internal source
files should include "nm-default.h", let "config.h" be included
by "nm-default.h" and include "nm-default.h" as first in every
source file.
We already wanted to include "nm-default.h" before other headers
because it might contains some fixes (like "nm-glib.h" compatibility)
that is required first.
- After including "nm-default.h", we optinally allow for including the
corresponding header file for the source file at hand. The idea
is to ensure that each header file is self contained.
- Don't include "config.h" or "nm-default.h" in any header file
(except "nm-sd-adapt.h"). Public headers anyway must not include
these headers, and internal headers are never included after
"nm-default.h", as of the first previous point.
- Include all internal headers with quotes instead of angle brackets.
In practice it doesn't matter, because in our public headers we must
include other headers with angle brackets. As we use our public
headers also to compile our interal source files, effectively the
result must be the same. Still do it for consistency.
- Except for <config.h> itself. Include it with angle brackets as suggested by
https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers
- "gsystem-local-alloc.h" and <gio/gio.h> are already included via
"nm-default.h". No need to include them separately.
- include "nm-macros-internal.h" via "nm-default.h" and drop all
explict includes.
- in the modified files, ensure that we always include "config.h"
and "nm-default.h" first. As second, include the header file
for the current source file (if applicable). Then follow external
includes and finally internal nm includes.
- include nm headers inside source code files with quotes
- internal header files don't need to include default headers.
They can savely assume that "nm-default.h" is already included
and with it glib, nm-glib.h, nm-macros-internal.h, etc.
The localization headers are now included via "nm-default.h".
Also fixes several places, where we wrongly included <glib/gi18n-lib.h>
instead of <glib/gi18n.h>. For example under "clients/" directory.
Rather than randomly including one or more of <glib.h>,
<glib-object.h>, and <gio/gio.h> everywhere (and forgetting to include
"nm-glib-compat.h" most of the time), rename nm-glib-compat.h to
nm-glib.h, include <gio/gio.h> from there, and then change all .c
files in NM to include "nm-glib.h" rather than including the glib
headers directly.
(Public headers files still have to include the real glib headers,
since nm-glib.h isn't installed...)
Also, remove glib includes from header files that are already
including a base object header file (which must itself already include
the glib headers).
Libraries need to include <gi18n-lib.h>, not <gi18n.h>, so that _()
will get defined to "dgettext (GETTEXT_DOMAIN, string)" rather than
"gettext (string)" (which will use the program's default domain, which
works fine for programs in the NetworkManager tree, but not for
external users). Likewise, we need to call bindtextdomain() so that
gettext can find the translations if the library is installed in a
different prefix from the program using it (and
bind_textdomain_codeset(), so it will know the translations are in
UTF-8 even if the locale isn't).
(The fact that no one noticed this was broken before is because the
libraries didn't really start returning useful translated strings much
until 0.9.10, and none of the out-of-tree clients have been updated to
actually show those strings to users yet.)
config.h should be included from every .c file, and it should be
included before any other include. Fix that.
(As a side effect of how I did this, this also changes us to
consistently use "config.h" rather than <config.h>. To the extent that
it matters [which is not much], quotes are more correct anyway, since
we're talking about a file in our own build tree, not a system
include.)
A NMActiveConnection may disappear before a match with NMDevice is found. In
such case recheck_pending_activations() would never call the activation
callback and the client would hang indefinitely:
libnm-Message: PC: (0x95bf088) NMManager:active-connections => '['/org/freedesktop/NetworkManager/ActiveConnection/225']' (ao / NMActiveConnection)
libnm-Message: PC: (0x95bf088) NMManager:activating-connection => ''/'' (o / NMActiveConnection)
libnm-Message: PC: (0x95d0a28) NMActiveConnection:state => '4' (u)
libnm-Message: PC: (0x95d0a28) NMActiveConnection:devices => '[]' (ao / NMDevice)
libnm-Message: PC: (0x95bf088) NMManager:active-connections => '[]' (ao / NMActiveConnection)
*hang*
Let's listen for active-connection-removed and tear down the activation with
an error if the removed connection is one we're activating.
If the operation isn't canceled it returns an error, printing this:
/libnm/client-nm-running:
(/home/dcbw/Development/fdo/NetworkManager/libnm/tests/.libs/lt-test-nm-client:17983): libnm-WARNING **: updated_properties: error reading NMRemoteSettings properties: GDBus.Error:org.freedesktop.DBus.Error.NoReply: Message did not receive a reply (timeout by message bus)
/bin/sh: line 5: 17983 Trace/breakpoint trap ./libnm-test-launch.sh ${dir}$tst
FAIL: test-nm-client
which screws up testcases because they don't expect this message.
And in this case, since libnm knows that NM is exiting and will
just clear out the properties anyway, it's useless to print the message.
Consolidate NMClientError and NMObjectError (such that there is now
only one libnm-API-specific error domain). In particular, merge
NM_CONNECTION_ERROR_CONNECTION_REMOVED with
NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE as the new
NM_CONNECTION_ERROR_OBJECT_CREATION_FAILED.
Also make object_creation_failed() be a plain method rather than a
signal, since there's no reason for anyone to be connecting to it on
another object. And remove its GError argument because the subclass
can just create its own more-specific error.