It is possible (but unlikely) that there will be a non-empty list of
pending dispatches when we remove the last ref from a GMainContext.
Make sure we drop the refs on the sources appropriately.
Add a (now-working) testcase that demonstrates how to trigger the issue.
https://bugzilla.gnome.org/show_bug.cgi?id=139699
Fix some races introduced in be2c7b83c4a9c9d3aa76b1499c27ab19e0f4e470
while keeping the property that multiple handlers for the same unix
signal all get dispatched.
Also fix the behaviour of the source checking for pending signals when
it's created. No matter what we do here (clear the pending flag or not)
there is something that can go wrong.
If we clear the flag, we may prevent other sources from being
dispatched. If we don't clear it, we may end up dispatching the same
source twice (if we manage to dispatch it from its own thread before the
GLib worker has a chance to run).
Instead, run the full dispatch procedure when a new source is added. It
actually doesn't matter what thread this runs in since the lock is held.
https://bugzilla.gnome.org/show_bug.cgi?id=711090
In Windows development environments that have it, <unistd.h> is mostly
just a wrapper around several other native headers (in particular,
<io.h>, which contains read(), close(), etc, and <process.h>, which
contains getpid()). But given that some Windows dev environments don't
have <unistd.h>, everything that uses those functions on Windows
already needed to include the correct Windows header as well, and so
there is never any point to including <unistd.h> on Windows.
Also, remove some <unistd.h> includes (and a few others) that were
unnecessary even on unix.
https://bugzilla.gnome.org/show_bug.cgi?id=710519
Since the initial addition of BeOS support in 1999, there has only
been one update to it (in 2005, and it wasn't even very big). GLib is
known to not currently build on Haiku (or presumably actual BeOS)
without additional patching, and the fact that there isn't a single
G_OS_BEOS check in gio/ is suspicious.
Additionally, other than the GModule implementation, all of the
existing G_OS_BEOS checks are either (a) "G_OS_UNIX || G_OS_BEOS", or
(b) random minor POSIXy tweaks (include this header file rather than
that one, etc), suggesting that if we were going to support Haiku, it
would probably be simpler to treat it as a special kind of G_OS_UNIX
(as we do with Mac OS X) rather than as its own completely different
thing.
So, kill G_OS_BEOS.
https://bugzilla.gnome.org/show_bug.cgi?id=710519
g_source_add_child_source() releases the context lock before attaching
child_source to context. And this causes trouble if parent source is
blocked and g_main_dispatch() manages to lock the context mutex and call
unblock_source() before child_source gets attached to context.
To fix this we call g_source_attach_unlocked() before releasing the
context mutex.
https://bugzilla.gnome.org/show_bug.cgi?id=711064
When the source id reaches G_MAXUINT (just prior to overflow), we
record the existing source ids to prevent reassigning them. As we are
about to assign G_MAXUINT to the triggering source, that id should be
added as well.
https://bugzilla.gnome.org/show_bug.cgi?id=710002
This stack exists only to answer the question of "what is the currently
dispatching source" and is handled in a way that makes it very clear
that we don't need to be using a linked list at all...
Just store the GSource directly.
Independently discovered (and same solution) by Phillip Susi.
https://bugzilla.gnome.org/show_bug.cgi?id=709113
If someone creates a unix signal source for e.g. SIGINT, and then
removes it, reset the handler to SIG_DFL.
Not doing this was the source of race conditions in the
glib/tests/unix test, but this will also just make us a "good citizen"
by cleaning up.
For example, if a project temporarily creates a handler for SIGTERM,
and then later removes it, they almost certainly want SIGTERM to
revert to the default of terminating the process, rather than doing
nothing.
https://bugzilla.gnome.org/show_bug.cgi?id=704699
We can't reset the pending flag for a signal until we've traversed
the whole list, as the documentation clearly says that in case multiple
sources they all get invoked.
This is still racy if you get a signal after checking the flag
but before resetting it, but it was the same before. The correct
fix would be to use sigwait() or signalfd(), but that would mean
blocking all signals in all threads, which is not compatible
with existing applications.
https://bugzilla.gnome.org/show_bug.cgi?id=704322
When a child_source is added to a blocked source it has no context, yet we
call block_source on it that segfaults when it dereferences the NULL context
when it attempts to remove the file descriptors. To fix this we:
- Ensure that when we block a source, we don't attempt to remove its file
descriptors from a NULL context.
- Also ensure that when we attach a blocked source to a context, we don't add the
file descriptors to the context.
https://bugzilla.gnome.org/show_bug.cgi?id=701283
When unreffing a context with sources still attached, it would end up
unlocking an already-unlocked context, causing crashes on platforms
that (unlike Linux) actually check for that.
https://bugzilla.gnome.org/show_bug.cgi?id=697595
Since this is a new API this cycle it's a good time to add a doc comment
explicitly declaring that a confusing issue that could be resolved
either way has no specific defined behaviour.
This may allow us some additional freedom in future GMainContext work or
we may decide that one behaviour is more desirable than the other.
Adding file descriptors to a GSource provides similar functionality to
the old g_source_add_poll() API with two main differences.
First: the list of handles is managed internally and therefore users are
prevented from randomly modifying the ->events field. This prepares us
for an epoll future where changing the event mask is a syscall.
Second: keeping the list internally allows us to check the ->revents for
events for ourselves, allowing the source to skip implementing
check/prepare. This also prepares us for the future by allowing an
implementation that doesn't need to iterate over all of the sources
every time.
https://bugzilla.gnome.org/show_bug.cgi?id=686853
Allow for NULL GSourceFuncs.check() and .prepare().
For prepare() the source will be taken not to be ready and having an
infinite timeout. For check() the source will be taken not to be ready.
https://bugzilla.gnome.org/show_bug.cgi?id=686853
This avoids collecting the zombie child, which means that the PID
can't be reused. This prevents possible race conditions that might
occur were one to send e.g. SIGTERM to a child.
This race condition has always existed due to the way we called
waitpid() for the app, but the window was widened when we moved the
waitpid() calls into a separate thread.
If waitid() isn't available, we return NULL, and consumers of this
private API (namely, GSubprocess) will need to handle that.
https://bugzilla.gnome.org/show_bug.cgi?id=672102
0 is not a valid source id, but for long-lived programs that rapidly
create/destroy sources, it's possible for the source id to overflow.
We should handle this, because the documentation implies we will.
https://bugzilla.gnome.org/show_bug.cgi?id=687098
This is preparatory work for a future commit which will add a
"catchall" waitpid API. If we don't synchronize here with the worker
thread, race conditions are possible.
This also ensures we have an error message if someone adds a child
watch for a nonexistent pid, etc. Previously, we'd simply keep
calling waitpid() getting ECHILD, and ignoring it until the source was
removed. Now, we g_warning() and fire the source.
Thirdly, this ensures that the waitpid() call in gmain handles EINTR,
like the g_spawn_sync() one did.
https://bugzilla.gnome.org/show_bug.cgi?id=687061
Applications that use glib should not invoke waitpid with a first
argument that is nonpositive, because when such a waitpid is run in
one thread and glib waits for a subprocess in another, there is a race
condition, and the former waitpid can reap a process that was intended
for the latter. Mention this in the documentation for
g_child_watch_source_new, and in the diagnostic generated by
g_spawn_sync when its waitpid fails with errno equal to ECHILD.
Signed-off-by: Colin Walters <walters@verbum.org>
http://bugzilla.gnome.org/show_bug.cgi?id=687075
A parent source holds refs on its children, so if the child source is
destroyed, we need to drop that ref. Fix, and reorganize to make this
all more obvious.
https://bugzilla.gnome.org/show_bug.cgi?id=682560
If a context was freed with sources still attached, those sources
correctly got destroyed, but the corresponding GSourceList structs
were being leaked.
https://bugzilla.gnome.org/show_bug.cgi?id=682560
g_source_get_context() was checking that the source wasn't destroyed
(since a source doesn't hold a ref on its context, and so
source->context might point to garbage in that case). However, it's
useful to be allowed to call g_source_get_context() on a source that
is destroyed-but-currently-running.
So instead, let g_source_get_context() return the context whenever
it's non-NULL, and clear the source->context of any sources that are
still in a context's sources list when the context is freed. Since
sources are only removed from the list when the source is freed (not
when it is destroyed), this means that now whenever a source has a
non-NULL context pointer, then that pointer is valid.
This also means that g_source_get_time() will now return-if-fail
rather than crashing if it is called on a source whose context has
been destroyed.
Add tests to glib/tests/mainloop to verify that g_source_get_context()
and g_source_get_time() work on destroyed sources.
https://bugzilla.gnome.org/show_bug.cgi?id=661767
Child sources are supposed to be blocked when their parents are, so
when adding a source to a blocked source, block the child too. Fixes a
warning when unblocking the parent.
Many (if not "almost all") programs that spawn other programs via
g_spawn_sync() or the like simply want to check whether or not the
child exited successfully, but doing so requires use of
platform-specific functionality and there's actually a fair amount of
boilerplate involved.
This new API will help drain a *lot* of mostly duplicated code in
GNOME, from gnome-session to gdm. And we can see that some bits even
inside GLib were doing it wrong; for example checking the exit status
on Unix, but ignoring it on Windows.
https://bugzilla.gnome.org/show_bug.cgi?id=679691
Rather than having a single priority-ordered list of GSources, store a
list of queues of each priority level. This means that adding a source
is now O(n) in the number of unique priority levels currently being
used, rather than O(n) in the total number of sources.
https://bugzilla.gnome.org/show_bug.cgi?id=619329
A child source does not have a priority of its own; it must have the
same priority as its parent. Enforce this in
g_source_set_priority_unlocked().
https://bugzilla.gnome.org/show_bug.cgi?id=619329
When blocking a source that has child sources, we need to consider the
children blocked as well. Otherwise they will still trigger repeatedly
in an inner loop started from the parent source's callback.
https://bugzilla.gnome.org/show_bug.cgi?id=669260
And remove a comment about Windows in the fallback implementation that
no longer applies, since there's now a separate Windows-specific
implementation.