After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 764979 - Connect to server is unusable after cancelling a password dialog
Connect to server is unusable after cancelling a password dialog
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
3.21.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
: 758243 771160 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2016-04-13 07:00 UTC by Ondrej Holy
Modified: 2017-08-28 22:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gtkplacesview: fix uncancellable connections (1.15 KB, patch)
2016-04-27 19:10 UTC, Ernestas Kulik
rejected Details | Review
placesview: hold onto ref during (un)mount ops (2.12 KB, patch)
2016-09-05 11:52 UTC, Christian Kellner
committed Details | Review
placesview: properly recover from cancellation (1.92 KB, patch)
2016-09-05 11:52 UTC, Christian Kellner
committed Details | Review
placesview: override destory to cancel ongoing ops (5.40 KB, patch)
2016-09-05 11:53 UTC, Christian Kellner
committed Details | Review
placesview: keep reference during network fetching (1.87 KB, patch)
2016-09-05 11:53 UTC, Christian Kellner
committed Details | Review

Description Ondrej Holy 2016-04-13 07:00:07 UTC
1/ Other Locations -> Connect to Server: sftp://server -> Connect
2/ Password prompt is shown 
3/ Press Cancel on the password prompt

Connect to Server panel is insensitive and "linear spinner" in the entry is spinning, however it should handle the cancelled prompt and allow another connection...
Comment 1 Ernestas Kulik 2016-04-27 19:10:36 UTC
Created attachment 326889 [details] [review]
gtkplacesview: fix uncancellable connections

server_mount_ready_cb() would return early if the connection was
cancelled, without reversing the busy state, leaving the user unable to
connect to any other server.

This commit removes the offending code.
Comment 2 Carlos Soriano 2016-04-28 09:02:21 UTC
Review of attachment 326889 [details] [review]:

Thanks for digging into this Ernestas!

First, this code in nautilus is generated from gtk+ using the gtk-code-generator.sh in the src/gtk/ folder. So the fix should go in gtk+ and then run this script on nautilus to update it.

About the code itself, so there is a comment there that makes an assumption that if it is cancelled it's because it's in finalize. So that was wrong. But removing that code would cause a crash if the operation finish after the widget is finalized. So the patch is not correct neither.

I wonder how we could detect that we are in finalize in order to avoid accessing invalid data. I can only think about putting a private safe guard boolean "in_destruction" and check it. But I will let this to gtk+.
Comment 3 Carlos Soriano 2016-04-28 09:05:39 UTC
Also as an unrelated issue in the same code, realized that the code shows a error dialog if the error is G_IO_ERROR_FAILED_HANDLED. The documentation for the constant says "Do not display any error dialog."
Comment 4 Christian Kellner 2016-08-29 08:32:24 UTC
Most GVfs backends return G_IO_ERROR_FAILED_HANDLED in case the user cancels the dialog (at least sftp, ftp, afp, smb currently do), so this case needs to be handled correctly.
Comment 5 Christian Kellner 2016-09-04 09:44:38 UTC
There also seems to be a use-after-free because after triggering this bug, e.g. in a filechooser, and then closing the filechooser, there is a continuous stream of errors like this: Gtk-CRITICAL **: gtk_entry_progress_pulse: assertion 'GTK_IS_ENTRY (entry)' failed
Comment 6 Christian Kellner 2016-09-05 11:52:46 UTC
Created attachment 334797 [details] [review]
placesview: hold onto ref during (un)mount ops

During mount and unmount opertions we keep a reference to the
GtkPlacesView around, so we have a valid view for the callback
code, even in the case that othe external references have been
dropped (i.e. the containing window gets destroyed).
Comment 7 Christian Kellner 2016-09-05 11:52:53 UTC
Created attachment 334798 [details] [review]
placesview: properly recover from cancellation

The current code wrongly assumes that cancellation can only happen
as a result widget finalization, and consequentially does not
properly recover from it. Therefore if the operation is cancelled
as a result of user interaction, the entry is will stay disabled
and the spinner will keep spinning. This is fixed by removal of
the early bail out in case of cancellation.
Comment 8 Christian Kellner 2016-09-05 11:53:00 UTC
Created attachment 334799 [details] [review]
placesview: override destory to cancel ongoing ops

Since we hold on to a reference during (un)mount operations, we
don't trigger the cancellation of operations in finalize anymore.
Instead we now override the GtkWidget's destroy() and cancel any
ongoing operations there.
Comment 9 Christian Kellner 2016-09-05 11:53:07 UTC
Created attachment 334800 [details] [review]
placesview: keep reference during network fetching

Analogous to (un)mount operation, we now keep a reference around
during the ongoing operation and make use of the destroyed flag
to check if we are still alive or if we have been cancelled as
a result of the widget being destroyed.
Comment 10 Carlos Soriano 2016-09-05 13:47:12 UTC
Review of attachment 334797 [details] [review]:

This works as long as the parents are using g_object_unref, but not when the widget gets a destroy() directly, since that runs dispose(). The correct way to do this is to keep a weak reference with a callback and cancel everything in case that happens. You can take a look how we do it in nautilus-files-view.c for the new_folder dialog.

In any case, this is just my 2 cents, I'm not gtk+ dev :)
Comment 11 Carlos Soriano 2016-09-05 13:56:22 UTC
Review of attachment 334799 [details] [review]:

IMHO keeping a widget alive until a disk operation is finished is not the best way to deal with this situation. In nautilus we had some issues with this, basically the widget was still in the window for one minute which is not a good UX.
My comment on this patch would be to do similar to what I said before.
Comment 12 Christian Kellner 2016-09-05 17:36:07 UTC
Thanks for taking a look at the patches!

> This works as long as the parents are using g_object_unref, but not when the
> widget gets a destroy() directly, since that runs dispose().

I don't quite understand what you mean. In both cases gtk_places_view_destroy() should get called (as intended): a) gtk_widget_destroy() -> g_object_run_dispose() -> g_object_dispose -> gtk_widget_dispose() -> emit destroy signal -> gtk_places_view_destroy ()
b) g_object_unref on the last reference -> g_object_dispose -> see above 

> The correct way
> to do this is to keep a weak reference with a callback and cancel everything
> in case that happens. You can take a look how we do it in
> nautilus-files-view.c for the new_folder dialog.

I don't see how that is any different to what the current code (before the patches) is doing, where we cancel the operation directly in the finalize method.

The main problem with the current code is that cancellation via the user leaves the UI broken (entry disabled, etc), which is due to the early exit in the error handling code. If we want to fix that and restore the UI we have to tell cancellation via the user apart from cancellation due to widget destruction. For this reason the patch keeps the reference to the view around so it can check for the destroyed flag. I am not sure who cancelling the operation via a callback from a weak ref would address this problem. 
I guess we could use a GWeakRef as an argument to all async functions (mount, unmount, network enumeration) and bail out if we can't acquire the strong reference. I don't believe the current patches would make "the widget be in the window for one minute" after destruction though.
Comment 13 Carlos Soriano 2016-09-05 20:11:25 UTC
(In reply to Christian Kellner from comment #12)
> Thanks for taking a look at the patches!
> 
> > This works as long as the parents are using g_object_unref, but not when the
> > widget gets a destroy() directly, since that runs dispose().
> 
> I don't quite understand what you mean. In both cases
> gtk_places_view_destroy() should get called (as intended): a)
> gtk_widget_destroy() -> g_object_run_dispose() -> g_object_dispose ->
> gtk_widget_dispose() -> emit destroy signal -> gtk_places_view_destroy ()
> b) g_object_unref on the last reference -> g_object_dispose -> see above 
> 

Ah yeah indeed, this was a review of the first patch that didn't contain the upcoming patches.

> > The correct way
> > to do this is to keep a weak reference with a callback and cancel everything
> > in case that happens. You can take a look how we do it in
> > nautilus-files-view.c for the new_folder dialog.
> 
> I don't see how that is any different to what the current code (before the
> patches) is doing, where we cancel the operation directly in the finalize
> method.
> 
> The main problem with the current code is that cancellation via the user
> leaves the UI broken (entry disabled, etc), which is due to the early exit
> in the error handling code. If we want to fix that and restore the UI we
> have to tell cancellation via the user apart from cancellation due to widget
> destruction. For this reason the patch keeps the reference to the view
> around so it can check for the destroyed flag. I am not sure who cancelling
> the operation via a callback from a weak ref would address this problem. 
> I guess we could use a GWeakRef as an argument to all async functions
> (mount, unmount, network enumeration) and bail out if we can't acquire the
> strong reference. I don't believe the current patches would make "the widget
> be in the window for one minute" after destruction though.

Oh yeah exactly, I just think it's cleaner using a gweakref and some struct data or so instead than using the view priv. But yeah, you got it right.

"and bail out if we can't acquire the strong reference"
I'm not sure I understood this. In any case, the weakref allows us to know whether the widget was destroyed to differentiate between destruction and user cancellation.

As said just my 2 cents, probably at this point it's just a matter of opinion/taste.
Comment 14 Matthias Clasen 2016-09-09 20:54:29 UTC
I think those patches are fine as-is.
Comment 15 Matthias Clasen 2016-09-09 20:57:29 UTC
Attachment 334797 [details] pushed as 3ed2594 - placesview: hold onto ref during (un)mount ops
Attachment 334798 [details] pushed as 0e5b0b7 - placesview: properly recover from cancellation
Attachment 334799 [details] pushed as 7cdc04c - placesview: override destory to cancel ongoing ops
Attachment 334800 [details] pushed as d4bf215 - placesview: keep reference during network fetching
Comment 16 Carlos Soriano 2016-09-12 08:19:10 UTC
*** Bug 771160 has been marked as a duplicate of this bug. ***
Comment 17 António Fernandes 2017-08-28 22:22:45 UTC
*** Bug 758243 has been marked as a duplicate of this bug. ***