This WIP patch moves the Windows Directory Monitoring code to the new
GLocalFileMonitor mechanism, and adds file monitoring in the process.
Progress from previous patch:
-File renames are now properly supported, but G_FILE_MONITOR_EVENT_MOVED_IN
and G_FILE_MONITOR_EVENT_MOVED_OUT needs to be investigated, as
ReadDirectoryChangesW() seems to send FILE_ACTION_REMOVED when a file is
moved out of a directory.
-Events are handled for both the long and short (8.3) variants of the
filenames, and files monitored will report changes when it is changed
via its short or long filenames.
Things to be done:
-Perhaps find out about attribute changes in files in a monitored
directory; if a file is monitored, attribute changes are correctly
handled.
-Investigate on G_FILE_MONITOR_EVENT_MOVED_OUT,
G_FILE_MONITOR_EVENT_MOVED_IN, G_FILE_MONITOR_EVENT_PRE_UNMOUNT,
G_FILE_MONITOR_EVENT_UNMOUNTED.
-Investigate on the "boredom" algoritm, and see how we can do it on
Windows.
https://bugzilla.gnome.org/show_bug.cgi?id=730116
Completely rewrite the FAM file monitor. Major changes:
- now runs in the worker thread
- dispatches events in a threadsafe way via GFileMonitorSource
- uses unix fd source instead of a GIOChannel
- is now simple enough to fit into one short file
This is the bare minimal effort. This seems not to crash immediately,
but it definitely needs some better testing.
The backend is not in good shape. It could use some serious work.
Use the "interesting" value from g_file_monitor_source_handle_event() to
decide if we're currently being flooded by a stream of boring events.
The main case here is when one or more files is being written to and the
change events are all being rate-limited in the GFileMonitor frontends.
In that case, we become "bored" with the event stream and add a backoff
timeout. In the case that it is exactly one large file being written
(which is the common case) then leaving the event in the queue also lets
the kernel perform merging on it, so when we wake up, we will only see
the one event. Even in the case that the kernel is unable to perform
merging, the context switch overhead will be vastly reduced.
In testing, this cuts down on the number of wake ups during a large file
copy, by a couple orders of magnitude (ie: less than 1% of the number of
wake ups).
Return an "interesting" boolean from the event handler function on
GFileMonitorSource.
An event was "interesting" if it will result in a signal actually being
dispatched to the user. It is "uninteresting" if it only hit an
already-dirty rate limiter.
We will use this information to do some backing off in the backends when
faced with a flood of uninteresting events.
We generally assume that an IN_CREATE event is the start of a series of
events in which another process is doing this:
fd = creat (...) -> IN_CREATE
write (fd, ..) -> IN_MODIFY
write (fd, ..) -> IN_MODIFY
close (fd) -> IN_CLOSE_WRITE
and as such, we use the CHANGES_DONE_HINT event after CREATED in order
to show when this sequence of events has completed (ie: when we receive
IN_CLOSE_WRITE when the user closes the file).
Renaming a file into place is handled by IN_MOVED_FROM so we don't have
to worry about that.
There are many other cases, however, where a new file 'appears' in a
directory in its completed form already, and the kernel reports
IN_CREATE. Examples include mkdir, mknod, and the creation of
hardlinks. In these cases, there is no corresponding IN_CLOSE_WRITE
event and the CHANGES_DONE_HINT will have to be emitted by an arbitrary
timeout.
Try to detect some of these cases and report CHANGES_DONE_HINT
immediately.
This is not perfect. There are some cases that will not be reliably
detected. An example is if the user makes a hardlink and then
immediately deletes the original (before we can stat the new file).
Another example is if the user creates a file with O_TMPFILE. In both
of these cases, CHANGES_DONE_HINT will still eventually be delivered via
the timeout.
Remove all event merging and dispatch logic from GFileMonitor. The only
implementation of GFileMonitor outside of glib is in gvfs and it already
does these things properly.
Get rid of GLocalDirectoryMonitor. We will use a single class,
GLocalFileMonitor, for both directory and file monitoring. This will
prevent every single backend from having to create two objects
separately (eg: ginotifydirectorymonitor.c and ginotifyfilemonitor.c).
Introduce GFileMonitorSource as a thread-safe cross-context dispatch
mechanism. Put it in GLocalFileMonitor. All backends will be expected
to dispatch via the source and not touch the GFileMonitor object at all
from the worker thread.
Remove all construct properties from GLocalFileMonitor and remove the
"context" construct property from GFileMonitor. All backends must now
get the information about what file to monitor from the ->start() call
which is mandatory to implement.
Remove the implementation of rate limiting in GFileMonitor and add an
implementation in GLocalFileMonitor. gvfs never did anything with this
anyway, but if it wanted to, it would have to implement it for itself.
This was done in order to get the rate_limit field into the
GFileMonitorSource so that it could be safely accessed from the worker
thread.
Expose g_local_file_is_remote() internally for NFS detection.
With the "is_remote" functionality exposed, we can now move all
functions for creating local file monitors to a proper location in
glocalfilemonitor.c
Port the inotify backend to adjust to the changes above. None of the
other backends are ported yet. Those will come in future commits.
Remove the hardwired 1 second event queue logic from inotify-kernel and
replace it with something vastly less complicated.
Events are now reported as soon as is possible instead of after a
delay.
We still must delay IN_MOVED_FROM events in order to look for the
matching IN_MOVED_TO events, and since we want to report events in order
this means that events behind those events can also be delayed. We
limit ourselves, however:
- no more than 100 events can be delayed at a time
- no event can be delayed by more than 10ms
https://bugzilla.gnome.org/show_bug.cgi?id=627285
Add a new internal constructor for GLocalFile (which itself is private).
This new constructor allows creating a GLocalFile from a dirname and a
basename, assuming that the dirname is already in canonical form and the
basename is a regular basename.
This will be used for creating GLocalFile instances from the file
monitoring code (for signal emissions).
For all of the effort spent ensuring that this algorithm would be
correctly threadsafe, I messed up the order of operations within a
single thread when porting to the new approach.
Fix that up.
Also: fix some overzealous asserting in the testcases. Since shutdown
is now lazy, we can never surely say !is_running at any particular point
in time.
This can be used to query whether the task has completed, in the sense
that it has had a result set on it, and has already – or will soon –
invoke its callback function.
Notifications for this property are emitted immediately after the task’s
main callback, in the same main context as that callback. This allows
for multiple bits of code to listen for completion of the GTask, which
opens the door for blocking on cancellation of the GTask and improved
handling of ‘pending’ behaviour.
https://bugzilla.gnome.org/show_bug.cgi?id=743636
g_socket_client_add_application_proxy() claimed "When the indicated
proxy protocol is returned by the #GProxyResolver, #GSocketClient will
consider this protocol as supported but will not try to find a #GProxy
instance to handle handshaking." But in fact, it did the checks in the
wrong order, so GProxy proxies ended up overriding
application-specified ones. Fix that.
Also, simplify the code a bit by making use of g_hash_table_add() and
g_hash_table_contains().
https://bugzilla.gnome.org/show_bug.cgi?id=733876
Currently, the Windows code use Winsock2-specific APIs to try to emulate
calls such as inet_pton(), inet_ntop() and if_nametoindex(), which may not
do the job all the time. On Vista and later, Winsock2 does provide a
proper implementation for these functions, so we can use them if they exist
on the system, by querying for them during g_networking_init(). Otherwise,
we continue to use the original code path for these, in the case of XP and
Server 2003.
This enables many of the network-address tests to pass on Windows as a
result, when the native Winsock2 implementations can be used.
https://bugzilla.gnome.org/show_bug.cgi?id=730352
Check the IPv6 addresses on Windows, as we need to reject those that have
brackets/ports around them as valid addresses in this form would have been
accepted during the call to g_inet_address_new_from_string ().
https://bugzilla.gnome.org/show_bug.cgi?id=730352
There was a theoretical deadlock between the worker trying to emit a
signal at the same time as we were waiting for it to shutdown the
notification (while holding the lock).
The deadlock was particularly annoying because we didn't really need to
wait for the shutdown and because it wasn't possible to signals to
arrive while waiting for a start. Attempting to deal with start and
stop in an asymmetric way could have lead to other weird situations,
however.
Drop the lock while waiting for the worker thread to start. This means
that we face the possibility of multiple waiters on the cond at the same
time, so we need to make more of a state machine.
https://bugzilla.gnome.org/show_bug.cgi?id=742599
GUnixMountMonitor was not threadsafe before. It was a global singleton
which emitted signals in the first thread that happened to construct it.
Move it to a per-context singleton model where each GMainContext gets
its own GUnixMountMonitor. Monitor for the changes from the GLib worker
thread and dispatch the results to each context with an active monitor.
https://bugzilla.gnome.org/show_bug.cgi?id=742599
Deprecate g_unix_mount_monitor_set_rate_limit() and turn it into a
no-op.
This function doesn't behave as advertised. It only controls rate
limiting for filesystem-based monitors. It has no impact over reporting
mount changes on Linux, for example, because those are based on polling
for changes in /proc (which doesn't use filesystem monitors). It also
has no impact on Mac OS because a library interface is used there.
This was added in https://bugzilla.gnome.org/show_bug.cgi?id=521946 in
order to be used by HAL, which is effectively dead. udisks no longer
uses this code at all.
https://bugzilla.gnome.org/show_bug.cgi?id=742599
This is a singleton, but we have a function called _new() to get it.
What's worse is that the documentation makes no mention of this, and
actually specifically says that a new monitor will be created each time.
https://bugzilla.gnome.org/show_bug.cgi?id=742599
Add a new internal helper called GContextSpecificGroup.
This is a mechanism for helping to maintain a group of context-specific
monitor objects (eg: GAppInfoMonitor, GUnixMountMonitor).
https://bugzilla.gnome.org/show_bug.cgi?id=742599
If someone explicitly calls g_application_quit() then don't attempt to
drain the mainloop of remaining sources.
This allows applications with 100% CPU utilisation to quit reliably.
https://bugzilla.gnome.org/show_bug.cgi?id=744876
We install win32-software/autorun.exe (as test data for mime scanning)
only on UNIX builds, so don't attempt to chmod it on 'make install'
unless we're on UNIX.
I love Emacs keyboard macros, used them to convert the list of
defines cleverly into a list of tests, then iterated and filled in
the necessary constructor arguments.
After ::shutdown, run the mainloop until all pending activity is
handled, before returning from run().
Among other things, this gives a chance for destroyed windows to be
properly withdrawn from the windowing system.
https://bugzilla.gnome.org/show_bug.cgi?id=744876
This is *significantly* more pleasant to use from C (while handling
errors and memory cleanup).
While we're here, change some ugly, leaky code in
tests/desktop-app-info.c to use it, in addition to a test case
in tests/file.c.
https://bugzilla.gnome.org/show_bug.cgi?id=661554
g_application_bind_busy_property() had the restriction that only one
property can be bound per object, so that NULL could be used to unbind.
Even though this is enough for most uses, it is a weird API.
Lift that restriction and add an explicit unbind function.
https://bugzilla.gnome.org/show_bug.cgi?id=744565