The only exceptions are those of the trivial getters/setters that don't
already need the initialization check for its secondary role as a memory
barrier (this is consistent with GSocket, where trivial getters/setters
don't check):
* g_dbus_connection_set_exit_on_close
* g_dbus_connection_get_exit_on_close
* g_dbus_connection_is_closed
g_dbus_connection_set_exit_on_close needs to be safe for
use before initialization anyway, so it can be set at construct-time.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661689
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: David Zeuthen <davidz@redhat.com>
Also document which fields require such a check in order to have correct
threading semantics.
This usage doesn't matches the GInitable documentation, which suggests
use of a GError - but using an uninitialized GDBusConnection is
programming error, and not usefully recoverable. (The GInitable
documentation may have been a mistake - GNOME#662208.) Also, not all of
the places where we need it can raise a GError.
The check serves a dual purpose: it turns a non-deterministic crash into
a deterministic critical warning, and is also a memory barrier for
thread-safety. All of these functions dereference or return fields that
are meant to be protected by FLAG_INITIALIZED, so they could crash or
return an undefined value to their caller without this, if called from a
thread that isn't the one that called initable_init() (although I can't
think of any way to do that without encountering a memory barrier,
undefined behaviour, or a race condition that leads to undefined
behaviour if the non-initializing thread wins the race).
One exception is that initable_init() itself makes a synchronous call.
We deal with that by passing new internal flags up the call stack, to
reassure g_dbus_connection_send_message_unlocked() that it can go ahead.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661689
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661992
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: David Zeuthen <davidz@redhat.com>
The comment implied that even failed initialization would set
is_initialized = TRUE, but this wasn't the case - failed initialization
would only set initialization_error, and it was necessary to check both.
It turns out the documented semantics are nicer than the implemented
semantics, since this lets us use atomic operations, which are also
memory barriers, to avoid needing separate memory barriers or locks
for initialization_error (and other members that are read-only after
construction).
I expect to need more than one atomically-accessed flag to fix thread
safety, so instead of a minimal implementation I've turned is_initialized
into a flags word.
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661689
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661992
Reviewed-by: David Zeuthen <davidz@redhat.com>
For some reason, the setting of g_atomic_lock_free wasn't making it down
to the lower part of the configure script where glibconfig.h was being
generated when building using mingw32-configure.
If we prefix glib_cv_ to the start of the variable name (like everyone
else is doing) then it magically starts working.
I love you, automake.
We didn't previously test anything except the implicit default of TRUE.
Now we test implicit TRUE, explicit TRUE, explicit FALSE, and
disconnecting at the local end (which regressed while fixing Bug #651268).
Also avoid some questionable use of a main context, which fell foul of
Bug #658999 and caused this test to be disabled in master.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=662100
Bug-NB: NB#287088
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: David Zeuthen <davidz@redhat.com>
This was a regression caused by my previous work on GDBusWorker thread-safety
(Bug #651268). The symptom is that if you disconnect a GDBusConnection
locally, the default implementation of GDBusConnection::closed
terminates your process, even though it shouldn't do that for
locally-closed connections; this is because GDBusWorker didn't think a
cancelled read was a local close.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=662100
Bug-NB: NB#287088
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: David Zeuthen <davidz@redhat.com>
pthreads doesn't implement the _lock_full() and _unlock_full() calls on
recursive mutexes so we don't have it on GRecMutex either. Now that
we're using GRecMutex to implement GStaticRecMutex, we have to fake it
by keeping an internal counter of the number of locks and calling
g_rec_mutex_unlock() the appropriate number of times.
The code to do this looked like:
depth = mutex->depth;
while (mutex->depth--)
g_rec_mutex_unlock (rm);
return depth;
which unfortunately did one last decrement after mutex->depth was
already zero (leaving it equal to -1).
When locked the next time, the count would then increase from -1 to 0
and then the next _unlock_full() call would not do any calls to
g_rec_mutex_unlock(), leading to a deadlock.
https://bugzilla.gnome.org/show_bug.cgi?id=661914
We clean up the detection of if we should do 'real' atomic operations or
mutex-emulated ones with the introduction of a new (public) macro:
G_ATOMIC_LOCK_FREE. If defined, our atomic operations are guaranteed to
be done in hardware.
We need to use __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 to determine if our
compiler supports GCC-style atomic operations from the gatomic.h header
because we might be building a program against GLib using a different
set of compiler options (or a different compiler) than was used to build
GLib itself.
Unfortunately, this macro is not available on clang, so it has currently
regressed to using the mutex emulation. A bug about that has been
opened here:
http://llvm.org/bugs/show_bug.cgi?id=11174
GDBusConnection sets the closed flag in the worker thread, then adds an
idle callback (which refs the Connection) to signal this in the main
thread. The tests session_bus_down doesn't spin the mainloop, so the
"closed" signal will always fire if iterating the mainloop later (and
drops the ref when doing so). But _is_closed can return TRUE even before
signalling this, in which case the "closed" signal isn't fired and the
ref isn't dropped, causing the test to fail.
Instead simply always wait for the closed signal, which is a good thing
to check anyway and ensures the ref is closed.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=661896
Reviewed-by: Matthias Clasen <mclasen@redhat.com>
This was turning all the GLIB_VARs in the glib headers into
dllexports on windows, causing all sort of nastiness. libgthread is
mostly empty now anyway, so we don't need any GLIB_COMPILATION like
flag.
-Move _glib_get_locale_dir to ggettext.c, as Matthias suggested
-Made up for the headers that needed to be included in ggettext.c to avoid
C4013 (implicit declaration of ...) errors/warnings
-gcharset.c, genviron.c, gunicollate.c: Some headers were missed in those
files that triggered C4013 warnings/errors (aka. implicit declaration
of ... in GCC). Make up for them here.
-gwin32.h: Only define g_win32_get_package_installation_directory/
g_win32_get_package_installation_subdirectory as macros
(alias of g_win32_get_package_installation_directory_utf8/
g_win32_get_package_installation_subdirectory_utf8) on Win64 (x64) as
g_win32_get_package_installation_directory/
g_win32_get_package_installation_subdirectory have seperate existing
implmentations for Win32-this is a long-standing problem but was covered-
up by G_DISABLE_DEPRECATED, which we are stopping to use as of 2.31.0.
Split win32 functions off into their own section, instead
of having large and unwieldy ifdef sections inside each function.
Also move the compat versions of env functions over from gutils.c
This was used as an optimisation for the macro hackery that used to live
in gthread.h. If a particular library or program knew that it could
rely on thread support being enabled, it would allow for static
evaluation of conditionals in some of those macros.
Since the macros are dead and thread support is now always-on, we can
get rid of this bit of legacy.
g_thread_init() is now a deprecated API, so drop G_DISABLE_DEPRECATED
from the CFLAGS for gthread/. Add the missing declaration for
g_thread_init_with_errorcheck_mutexes() back to deprecated/gthread.h.
This function was never put in a header and was only used internally
from libgthread, but we should keep the symbol around to avoid
triggering any false-positives on ABI checkers.
For -Wmissing-prototypes compatibility with this unusual case, we should
add a private prototype in the .c file just before.