Skip to content

Commit

Permalink
Fix blocking when listing or entering a network location with an
Browse files Browse the repository at this point in the history
inaccessible host.

A mounted network directory with a down host will cause stat to
block for 10 seconds before reporting failure.

In nemo, if that location is bookmarked, it can cause multiple
freezes at startup.

---

This is not a perfect fix - I don't think one is possible at the
application level.

Nemo will now check if a target's path is descended from a mounted
network connection, and skip any operation involving stat.

pros:
- Nemo will no longer freeze at startup due a 'dangling' network
  mount.
- Clicking on the bookmark will no longer freeze, but if the folder
  hasn't been explicitly accessed yet, there will be a delay of
  about 10s, then an error popup. Subsequent clicks will cause the
  error immediately.
- Navigating to the folder's parent directory will *always* cause
  a 10s delay in loading that folder. The file list will not
  include the bad directory.
con:
- The places-sidebar will always show any bookmarked network folder
  as available/online (no triangle warning icon), whether actually
  available or not.

ref: #3270 (maybe?), #3436, #1378.
  • Loading branch information
mtwebster committed Aug 28, 2024
1 parent 46313e6 commit fb47200
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
6 changes: 3 additions & 3 deletions libnemo-private/nemo-action.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ nemo_action_new (const gchar *name,
const gchar *prg_name = reverse ? deps[i] + 1 : deps[i];

if (g_path_is_absolute (prg_name)) {
if (g_file_test (prg_name, G_FILE_TEST_EXISTS)) {
if ((!nemo_path_is_network_safe (prg_name)) && g_file_test (prg_name, G_FILE_TEST_EXISTS)) {
found = TRUE;
}
} else {
Expand Down Expand Up @@ -1657,7 +1657,7 @@ get_is_dir (NemoFile *file)

GFile *f = nemo_file_get_location (file);

if (g_file_is_native (f)) {
if (g_file_is_native (f) && (!nemo_location_is_network_safe (f))) {
gchar *path;

path = g_file_get_path (f);
Expand Down Expand Up @@ -1958,7 +1958,7 @@ get_visibility (NemoAction *action,
f = nemo_file_get_location (file);

if (g_file_is_native (f)) {
mount = g_file_find_enclosing_mount (f, NULL, NULL);
mount = nemo_get_mount_for_location_safe (f);
nemo_file_set_mount (file, mount);
}

Expand Down
3 changes: 2 additions & 1 deletion libnemo-private/nemo-bookmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,8 @@ nemo_bookmark_uri_get_exists (NemoBookmark *bookmark)

path_name = g_file_get_path (bookmark->details->location);

if (g_file_is_native (bookmark->details->location) && g_file_test (path_name, G_FILE_TEST_EXISTS)) {
if (g_file_is_native (bookmark->details->location) &&
(!nemo_location_is_network_safe (bookmark->details->location)) && g_file_test (path_name, G_FILE_TEST_EXISTS)) {
exists = TRUE;
} else {
g_signal_emit_by_name (bookmark, "location-mounted", bookmark->details->location, &exists);
Expand Down
86 changes: 85 additions & 1 deletion libnemo-private/nemo-file-utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,91 @@ nemo_user_is_root (void)
return elevated;
}

/* End copied section */
static gint
sort_by_length (GMount *a, GMount *b)
{
g_autoptr(GFile) a_root = g_mount_get_root (a);
g_autoptr(GFile) b_root = g_mount_get_root (b);
g_autofree gchar *a_uri = g_file_get_uri (a_root);
g_autofree gchar *b_uri = g_file_get_uri (b_root);
gint a_len = g_utf8_strlen (a_uri, -1);
gint b_len = g_utf8_strlen (b_uri, -1);

return b_len - a_len;
}

GMount *
nemo_get_mount_for_location_safe (GFile *location)
{
GVolumeMonitor *monitor;
GList *mounts = NULL;
GList *mount_iter;
GMount *ret = NULL;


monitor = g_volume_monitor_get ();
mounts = g_volume_monitor_get_mounts (monitor);

mounts = g_list_sort (mounts, (GCompareFunc) sort_by_length);

for (mount_iter = mounts; mount_iter != NULL; mount_iter = mount_iter->next) {
GMount *mount = G_MOUNT (mount_iter->data);
GFile *mount_location = g_mount_get_root (mount);
gchar *mount_root_uri = g_file_get_uri (mount_location);
gchar *location_uri = g_file_get_uri (location);

if (g_str_has_prefix (location_uri, mount_root_uri)) {
// Add a ref for our match, as it will lose one when the list is freed.
ret = g_object_ref (mount);
}

g_free (mount_root_uri);
g_free (location_uri);
g_object_unref (mount_location);

if (ret != NULL)
break;
}

g_list_free_full (mounts, (GDestroyNotify) g_object_unref);
g_object_unref (monitor);

return ret;
}

gboolean
nemo_location_is_network_safe (GFile *location)
{
GVolume *volume;
GMount *mount;
gboolean is_network = FALSE;

mount = nemo_get_mount_for_location_safe (location);
if (mount != NULL) {
volume = g_mount_get_volume (mount);
if (volume != NULL) {
g_autofree gchar *identifier = g_volume_get_identifier (volume, "class");

if (g_strcmp0 (identifier, "network") == 0) {
is_network = TRUE;
}

g_object_unref (volume);
}

g_object_unref (mount);
}

return is_network;
}

gboolean
nemo_path_is_network_safe (const gchar *path)
{
g_autoptr(GFile) location = g_file_new_for_path (path);

return nemo_location_is_network_safe (location);
}

#if !defined (NEMO_OMIT_SELF_CHECK)

Expand Down
4 changes: 4 additions & 0 deletions libnemo-private/nemo-file-utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,8 @@ gchar *nemo_get_best_guess_file_mimetype (const gchar *filename,

gboolean nemo_treating_root_as_normal (void);
gboolean nemo_user_is_root (void);

GMount *nemo_get_mount_for_location_safe (GFile *location);
gboolean nemo_location_is_network_safe (GFile *location);
gboolean nemo_path_is_network_safe (const gchar *path);
#endif /* NEMO_FILE_UTILITIES_H */

1 comment on commit fb47200

@LinuxOnTheDesktop
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this. Might I ask the following? What happens if the down host comes back up? ('Subsequent clicks will cause the error immediately.')

Please sign in to comment.