Marco Trevisan (Treviño) has proposed merging ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic-xubuntu-cancel-search into ~ubuntu-desktop/ubuntu/+source/gnome-calculator:ubuntu/bionic with ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic as a prerequisite.
Requested reviews: Ubuntu Desktop (ubuntu-desktop) Related bugs: Bug #1756826 in nautilus (Ubuntu): "hangs when remote search provider performs expensive operation" https://bugs.launchpad.net/ubuntu/+source/nautilus/+bug/1756826 For more details, see: https://code.launchpad.net/~3v1n0/ubuntu/+source/gnome-calculator/+git/gnome-calculator/+merge/354335 -- Your team Ubuntu Desktop is requested to review the proposed merge of ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic-xubuntu-cancel-search into ~ubuntu-desktop/ubuntu/+source/gnome-calculator:ubuntu/bionic.
diff --git a/debian/changelog b/debian/changelog index a7346e1..ae09540 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,17 @@ gnome-calculator (1:3.28.2-1ubuntu1) UNRELEASED; urgency=medium - Use Ubuntu Vcs-* URIs, and move debian's to XS-Debian-Vcs-* * debian/gbp.conf: - update branches to point to ubuntu/bionic + d/p/search-provider-Use-async-calls-cancel-search-on-inactivi.patch, + d/p/search-provider-renew-inactivity-timeout-at-each-calculat.patch, + d/p/search-provider-Use-lower-inactivity-timeout.patch, + d/p/search-provider-simplify-solve_subprocess.patch, + d/p/search-provider-cache-equations-avoiding-spawning-calcula.patch, + d/p/search-provider-cancel-the-current-process-on-new-calcula.patch, + d/p/search-provider-cache-only-a-limited-number-of-equations.patch, + d/p/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch: + - Make search provider async and support XUbuntuCancel method to + stop expensive operations that might lead to an unresponsive + process (LP: #1756826) -- Marco Trevisan (Treviño) <ma...@ubuntu.com> Wed, 05 Sep 2018 15:26:32 +0200 diff --git a/debian/control b/debian/control index cd4706c..0782192 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,8 @@ Source: gnome-calculator Section: math Priority: optional -Maintainer: Debian GNOME Maintainers <pkg-gnome-maintain...@lists.alioth.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-disc...@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintain...@lists.alioth.debian.org> Uploaders: Jeremy Bicha <jbi...@debian.org>, Laurent Bigonville <bi...@debian.org>, Michael Biebl <bi...@debian.org> Build-Depends: appstream-util, debhelper (>= 11.1.3), diff --git a/debian/control.in b/debian/control.in index b5194ee..d9e0327 100644 --- a/debian/control.in +++ b/debian/control.in @@ -1,7 +1,8 @@ Source: gnome-calculator Section: math Priority: optional -Maintainer: Debian GNOME Maintainers <pkg-gnome-maintain...@lists.alioth.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-disc...@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintain...@lists.alioth.debian.org> Uploaders: @GNOME_TEAM@ Build-Depends: appstream-util, debhelper (>= 11.1.3), diff --git a/debian/patches/search-provider-Use-async-calls-cancel-search-on-inactivi.patch b/debian/patches/search-provider-Use-async-calls-cancel-search-on-inactivi.patch new file mode 100644 index 0000000..324be46 --- /dev/null +++ b/debian/patches/search-provider-Use-async-calls-cancel-search-on-inactivi.patch @@ -0,0 +1,232 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Fri, 24 Aug 2018 06:57:03 +0200 +Subject: search-provider: Use async calls, cancel search on inactivity + +Move to async methods everywhere and factorize the `solve` calls to a single +method that only uses Subprocess and that can be cancelled. + +As per this, if the the search-provider is trying to compute some complex +operation, the daemon won't hang and once the applications' inactivity +timeout is hit, any running instance of gnome-calculator will be killed and +the daemon will return accordingly. + +This reduces the impact of an issue that can cause gnome-calculator to keep +running forever if a complex computation is required (10!!!) from the shell, +and won't ever be killed (see GNOME/gnome-shell#183). + +This is also a prerequisite for supporting the search Cancellation that is +going to be available on next version of the Search provider protocol +(as per GNOME/gnome-shell#436) + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 126 +++++++++++++++++++++++++---------- + 1 file changed, 89 insertions(+), 37 deletions(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index 26c72af..659f73d 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -1,6 +1,7 @@ + /* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * Copyright (C) 2014 Michael Catanzaro ++ * Copyright (C) 2018 Marco Trevisan + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software +@@ -12,17 +13,85 @@ + [DBus (name = "org.gnome.Shell.SearchProvider2")] + public class SearchProvider : Object + { ++ private Cancellable cancellable = new Cancellable (); ++ ++ ~SearchProvider () ++ { ++ cancel (); ++ } ++ ++ [DBus (visible = false)] ++ public void cancel () ++ { ++ if (cancellable != null) ++ { ++ cancellable.cancel (); ++ } ++ } ++ + private static string terms_to_equation (string[] terms) + { + return string.joinv (" ", terms); + } + +- private static bool can_parse (string[] terms) ++ private async Subprocess solve_subprocess (string equation, bool return_solution = false, out string? solution_buf = null) throws Error + { ++ Subprocess subprocess; ++ string[] argv = {"gnome-calculator", "--solve"}; ++ argv += equation; ++ argv += null; ++ ++ debug (@"Trying to solve $(equation)"); ++ + try + { +- int exit_status; ++ // Eat output so that it doesn't wind up in the journal. It's ++ // expected that most searches are not valid calculator input. ++ var flags = SubprocessFlags.STDERR_PIPE; ++ ++ if (return_solution) ++ { ++ flags |= SubprocessFlags.STDOUT_PIPE; ++ } ++ ++ subprocess = new Subprocess.newv (argv, flags); ++ } ++ catch (Error e) ++ { ++ error ("Failed to spawn Calculator: %s", e.message); ++ } ++ ++ try ++ { ++ string stderr_buf; ++ ++ cancellable = new Cancellable (); ++ cancellable.cancelled.connect (() => { ++ subprocess.force_exit (); ++ cancellable = null; ++ }); ++ ++ yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf); ++ } ++ catch (Error e) ++ { ++ if (e is IOError.CANCELLED) ++ { ++ throw e; ++ } ++ else ++ { ++ error ("Failed reading result: %s", e.message); ++ } ++ } + ++ return subprocess; ++ } ++ ++ private async bool can_parse (string[] terms) ++ { ++ try ++ { + var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP); + if (tsep_string == null || tsep_string == "") + tsep_string = " "; +@@ -39,14 +108,8 @@ public class SearchProvider : Object + return false; + } + +- // Eat output so that it doesn't wind up in the journal. It's +- // expected that most searches are not valid calculator input. +- string stdout_buf; +- string stderr_buf; +- Process.spawn_command_line_sync ( +- "gnome-calculator --solve " + Shell.quote (equation), +- out stdout_buf, out stderr_buf, out exit_status); +- Process.check_exit_status (exit_status); ++ var subprocess = yield solve_subprocess (equation); ++ yield subprocess.wait_check_async (); + } + catch (SpawnError e) + { +@@ -60,54 +123,37 @@ public class SearchProvider : Object + return true; + } + +- private static string[] get_result_identifier (string[] terms) +- ensures (result.length == 0 || result.length == 1) ++ private async string[] get_result_identifier (string[] terms) + { + /* We have at most one result: the search terms as one string */ +- if (can_parse (terms)) ++ if (yield can_parse (terms)) + return { terms_to_equation (terms) }; + else + return new string[0]; + } + +- public string[] get_initial_result_set (string[] terms) ++ public async string[] get_initial_result_set (string[] terms) + { +- return get_result_identifier (terms); ++ return yield get_result_identifier (terms); + } + +- public string[] get_subsearch_result_set (string[] previous_results, string[] terms) ++ public async string[] get_subsearch_result_set (string[] previous_results, string[] terms) + { +- return get_result_identifier (terms); ++ return yield get_result_identifier (terms); + } + +- public HashTable<string, Variant>[] get_result_metas (string[] results) ++ public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender) + requires (results.length == 1) +- ensures (result.length == 1) + { +- Subprocess subprocess; + string stdout_buf; +- string stderr_buf; +- +- string[] argv = {"gnome-calculator", "--solve"}; +- argv += results[0]; +- argv += null; +- +- try +- { +- subprocess = new Subprocess.newv (argv, SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_PIPE); +- } +- catch (Error e) +- { +- error ("Failed to spawn Calculator: %s", e.message); +- } + + try + { +- subprocess.communicate_utf8 (null, null, out stdout_buf, out stderr_buf); ++ yield solve_subprocess (results[0], true, out stdout_buf); + } + catch (Error e) + { +- error ("Failed reading result: %s", e.message); ++ return new HashTable<string, Variant>[0]; + } + + var metadata = new HashTable<string, Variant>[1]; +@@ -155,9 +201,11 @@ public class SearchProviderApp : Application + + public override bool dbus_register (DBusConnection connection, string object_path) + { ++ SearchProvider search_provider = new SearchProvider (); ++ + try + { +- connection.register_object (object_path, new SearchProvider ()); ++ connection.register_object (object_path, search_provider); + } + catch (IOError error) + { +@@ -165,6 +213,10 @@ public class SearchProviderApp : Application + quit (); + } + ++ shutdown.connect (() => { ++ search_provider.cancel (); ++ }); ++ + return true; + } + } diff --git a/debian/patches/search-provider-Use-lower-inactivity-timeout.patch b/debian/patches/search-provider-Use-lower-inactivity-timeout.patch new file mode 100644 index 0000000..b5b0dd6 --- /dev/null +++ b/debian/patches/search-provider-Use-lower-inactivity-timeout.patch @@ -0,0 +1,29 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Fri, 24 Aug 2018 07:12:12 +0200 +Subject: search-provider: Use lower inactivity timeout + +Since we're renewing it at every call involving a process call, we can just +set it to a lower value than the default dbus proxy timeout, so that the provider +will return invalid values before that the timeout has been hit. + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index 7e54fa6..9035c58 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -203,7 +203,8 @@ public class SearchProviderApp : Application + { + Object (application_id: "org.gnome.Calculator.SearchProvider", + flags: ApplicationFlags.IS_SERVICE, +- inactivity_timeout: 60000); ++ inactivity_timeout: 20000); ++ } + + public void renew_inactivity_timeout () + { diff --git a/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch b/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch new file mode 100644 index 0000000..b3903df --- /dev/null +++ b/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch @@ -0,0 +1,170 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Mon, 27 Aug 2018 18:45:34 +0200 +Subject: search-provider: cache equations avoiding spawning calculator twice + +Currently we spawn the calculator two times for each operation, one to check +if the search provider is valid for such syntax, the other time to actually +present the results. But since these results are just available at first +call, we can just keep them around and return them if the shell requires them. + +Since the search provider deamon is kept alive for just few moments, there's +no real need to cleanup the cache using a queue. + +In case of multiple async calls, reuse cancellable instead so that we can +just kill all the related processes one time at once. + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 79 ++++++++++++++++++++---------------- + 1 file changed, 45 insertions(+), 34 deletions(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index a3c57f7..af2779e 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -14,10 +14,13 @@ + public class SearchProvider : Object + { + private unowned SearchProviderApp application; +- private Cancellable cancellable = new Cancellable (); ++ private Cancellable cancellable; ++ ++ private HashTable<string, string> cached_equations; + public SearchProvider (SearchProviderApp app) + { + application = app; ++ cached_equations = new HashTable<string, string> (str_hash, str_equal); + } + + ~SearchProvider () +@@ -29,9 +32,7 @@ public class SearchProvider : Object + public void cancel () + { + if (cancellable != null) +- { + cancellable.cancel (); +- } + } + + private static string terms_to_equation (string[] terms) +@@ -60,7 +61,9 @@ public class SearchProvider : Object + error ("Failed to spawn Calculator: %s", e.message); + } + +- cancellable = new Cancellable (); ++ if (cancellable == null) ++ cancellable = new Cancellable (); ++ + cancellable.cancelled.connect (() => { + subprocess.force_exit (); + cancellable = null; +@@ -71,29 +74,36 @@ public class SearchProvider : Object + return subprocess; + } + +- private async bool can_parse (string[] terms) ++ private async bool solve_equation (string equation) + { +- try +- { +- var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP); +- if (tsep_string == null || tsep_string == "") +- tsep_string = " "; ++ string? result; + +- var decimal = Posix.nl_langinfo (Posix.NLItem.RADIXCHAR); +- if (decimal == null) +- decimal = ""; ++ cancel(); + +- // "normalize" input to a format known to double.try_parse +- var equation = terms_to_equation (terms).replace (tsep_string, "").replace (decimal, "."); ++ var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP); ++ if (tsep_string == null || tsep_string == "") ++ tsep_string = " "; + +- cancel(); ++ var decimal = Posix.nl_langinfo (Posix.NLItem.RADIXCHAR); ++ if (decimal == null) ++ decimal = ""; + +- // if the search is a plain number, don't process it +- if (double.try_parse (equation)) { +- return false; +- } ++ // "normalize" input to a format known to double.try_parse ++ var normalized_equation = equation.replace (tsep_string, "").replace (decimal, "."); + +- (yield solve_subprocess (equation)).wait_check (cancellable); ++ // if the search is a plain number, don't process it ++ if (double.try_parse (normalized_equation)) { ++ return false; ++ } ++ ++ if (cached_equations.lookup (equation) != null) ++ return true; ++ ++ try ++ { ++ var subprocess = yield solve_subprocess (normalized_equation); ++ yield subprocess.communicate_utf8_async (null, cancellable, out result, null); ++ subprocess.wait_check (cancellable); + } + catch (SpawnError e) + { +@@ -104,14 +114,17 @@ public class SearchProvider : Object + return false; + } + ++ cached_equations.insert (equation, result.strip ()); ++ + return true; + } + + private async string[] get_result_identifier (string[] terms) + { + /* We have at most one result: the search terms as one string */ +- if (yield can_parse (terms)) +- return { terms_to_equation (terms) }; ++ var equation = terms_to_equation (terms); ++ if (yield solve_equation (equation)) ++ return { equation }; + else + return new string[0]; + } +@@ -129,24 +142,22 @@ public class SearchProvider : Object + public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender) + requires (results.length == 1) + { +- string stdout_buf; +- string stderr_buf; ++ string equation; ++ string result; + +- try +- { +- var subprocess = yield solve_subprocess (results[0]); +- yield subprocess.communicate_utf8_async (null, cancellable, out stdout_buf, out stderr_buf); +- } +- catch (Error e) +- { ++ equation = terms_to_equation (results); ++ ++ if (!yield solve_equation (equation)) + return new HashTable<string, Variant>[0]; +- } ++ ++ result = cached_equations.lookup (equation); ++ assert (result != null); + + var metadata = new HashTable<string, Variant>[1]; + metadata[0] = new HashTable<string, Variant>(str_hash, str_equal); + metadata[0].insert ("id", results[0]); + metadata[0].insert ("name", results[0] ); +- metadata[0].insert ("description", " = " + stdout_buf.strip ()); ++ metadata[0].insert ("description", @" = $result"); + + return metadata; + } diff --git a/debian/patches/search-provider-cache-only-a-limited-number-of-equations.patch b/debian/patches/search-provider-cache-only-a-limited-number-of-equations.patch new file mode 100644 index 0000000..ca1c342 --- /dev/null +++ b/debian/patches/search-provider-cache-only-a-limited-number-of-equations.patch @@ -0,0 +1,44 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Mon, 27 Aug 2018 18:56:09 +0200 +Subject: search-provider: cache only a limited number of equations + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index af2779e..fc72128 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -16,10 +16,15 @@ public class SearchProvider : Object + private unowned SearchProviderApp application; + private Cancellable cancellable; + ++ private const int MAX_CACHED_OPERATIONS = 10; ++ private Queue<string> queued_equations; + private HashTable<string, string> cached_equations; ++ + public SearchProvider (SearchProviderApp app) + { + application = app; ++ ++ queued_equations = new Queue<string> (); + cached_equations = new HashTable<string, string> (str_hash, str_equal); + } + +@@ -114,8 +119,12 @@ public class SearchProvider : Object + return false; + } + ++ queued_equations.push_tail (equation); + cached_equations.insert (equation, result.strip ()); + ++ if (queued_equations.length > MAX_CACHED_OPERATIONS) ++ cached_equations.remove (queued_equations.pop_head ()); ++ + return true; + } + diff --git a/debian/patches/search-provider-cancel-the-current-process-on-new-calcula.patch b/debian/patches/search-provider-cancel-the-current-process-on-new-calcula.patch new file mode 100644 index 0000000..801d844 --- /dev/null +++ b/debian/patches/search-provider-cancel-the-current-process-on-new-calcula.patch @@ -0,0 +1,29 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Thu, 30 Aug 2018 18:47:16 +0200 +Subject: search-provider: cancel the current process on new calculation + request + +As there's just one shell running at time, there's no point of supporting +parallel calls, we can just safely refer to the last equation as the only one +we need to compute. + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index df37b86..a3c57f7 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -86,6 +86,8 @@ public class SearchProvider : Object + // "normalize" input to a format known to double.try_parse + var equation = terms_to_equation (terms).replace (tsep_string, "").replace (decimal, "."); + ++ cancel(); ++ + // if the search is a plain number, don't process it + if (double.try_parse (equation)) { + return false; diff --git a/debian/patches/search-provider-renew-inactivity-timeout-at-each-calculat.patch b/debian/patches/search-provider-renew-inactivity-timeout-at-each-calculat.patch new file mode 100644 index 0000000..41458ad --- /dev/null +++ b/debian/patches/search-provider-renew-inactivity-timeout-at-each-calculat.patch @@ -0,0 +1,60 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Fri, 24 Aug 2018 07:10:17 +0200 +Subject: search-provider: renew inactivity timeout at each calculator run + +As per the async rewrite, now the daemon inactivity timeout might happen +when another call has just been done, while we don't want this to be the case. + +So, everytime we do a subprocess call, let's renew the application timeout. + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/100 +--- + search-provider/search-provider.vala | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index 659f73d..7e54fa6 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -13,7 +13,12 @@ + [DBus (name = "org.gnome.Shell.SearchProvider2")] + public class SearchProvider : Object + { ++ private unowned SearchProviderApp application; + private Cancellable cancellable = new Cancellable (); ++ public SearchProvider (SearchProviderApp app) ++ { ++ application = app; ++ } + + ~SearchProvider () + { +@@ -71,6 +76,8 @@ public class SearchProvider : Object + cancellable = null; + }); + ++ application.renew_inactivity_timeout (); ++ + yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf); + } + catch (Error e) +@@ -197,11 +204,16 @@ public class SearchProviderApp : Application + Object (application_id: "org.gnome.Calculator.SearchProvider", + flags: ApplicationFlags.IS_SERVICE, + inactivity_timeout: 60000); ++ ++ public void renew_inactivity_timeout () ++ { ++ this.hold (); ++ this.release (); + } + + public override bool dbus_register (DBusConnection connection, string object_path) + { +- SearchProvider search_provider = new SearchProvider (); ++ SearchProvider search_provider = new SearchProvider (this); + + try + { diff --git a/debian/patches/search-provider-simplify-solve_subprocess.patch b/debian/patches/search-provider-simplify-solve_subprocess.patch new file mode 100644 index 0000000..7dc1d78 --- /dev/null +++ b/debian/patches/search-provider-simplify-solve_subprocess.patch @@ -0,0 +1,113 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Fri, 24 Aug 2018 07:31:37 +0200 +Subject: search-provider: simplify solve_subprocess + +Only return a subprocess in solve_subprocess and make the callers deal with +the actual operation to perform. + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10 +--- + search-provider/search-provider.vala | 49 ++++++++++-------------------------- + 1 file changed, 13 insertions(+), 36 deletions(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index 9035c58..df37b86 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -39,7 +39,7 @@ public class SearchProvider : Object + return string.joinv (" ", terms); + } + +- private async Subprocess solve_subprocess (string equation, bool return_solution = false, out string? solution_buf = null) throws Error ++ private async Subprocess solve_subprocess (string equation) throws Error + { + Subprocess subprocess; + string[] argv = {"gnome-calculator", "--solve"}; +@@ -52,13 +52,7 @@ public class SearchProvider : Object + { + // Eat output so that it doesn't wind up in the journal. It's + // expected that most searches are not valid calculator input. +- var flags = SubprocessFlags.STDERR_PIPE; +- +- if (return_solution) +- { +- flags |= SubprocessFlags.STDOUT_PIPE; +- } +- ++ var flags = SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_PIPE; + subprocess = new Subprocess.newv (argv, flags); + } + catch (Error e) +@@ -66,31 +60,13 @@ public class SearchProvider : Object + error ("Failed to spawn Calculator: %s", e.message); + } + +- try +- { +- string stderr_buf; +- +- cancellable = new Cancellable (); +- cancellable.cancelled.connect (() => { +- subprocess.force_exit (); +- cancellable = null; +- }); +- +- application.renew_inactivity_timeout (); ++ cancellable = new Cancellable (); ++ cancellable.cancelled.connect (() => { ++ subprocess.force_exit (); ++ cancellable = null; ++ }); + +- yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf); +- } +- catch (Error e) +- { +- if (e is IOError.CANCELLED) +- { +- throw e; +- } +- else +- { +- error ("Failed reading result: %s", e.message); +- } +- } ++ application.renew_inactivity_timeout (); + + return subprocess; + } +@@ -115,8 +91,7 @@ public class SearchProvider : Object + return false; + } + +- var subprocess = yield solve_subprocess (equation); +- yield subprocess.wait_check_async (); ++ (yield solve_subprocess (equation)).wait_check (cancellable); + } + catch (SpawnError e) + { +@@ -153,10 +128,12 @@ public class SearchProvider : Object + requires (results.length == 1) + { + string stdout_buf; ++ string stderr_buf; + + try + { +- yield solve_subprocess (results[0], true, out stdout_buf); ++ var subprocess = yield solve_subprocess (results[0]); ++ yield subprocess.communicate_utf8_async (null, cancellable, out stdout_buf, out stderr_buf); + } + catch (Error e) + { +@@ -167,7 +144,7 @@ public class SearchProvider : Object + metadata[0] = new HashTable<string, Variant>(str_hash, str_equal); + metadata[0].insert ("id", results[0]); + metadata[0].insert ("name", results[0] ); +- metadata[0].insert ("description", " = " + stdout_buf.strip() ); ++ metadata[0].insert ("description", " = " + stdout_buf.strip ()); + + return metadata; + } diff --git a/debian/patches/series b/debian/patches/series index e69de29..4fd8ad8 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -0,0 +1,8 @@ +search-provider-Use-async-calls-cancel-search-on-inactivi.patch +search-provider-renew-inactivity-timeout-at-each-calculat.patch +search-provider-Use-lower-inactivity-timeout.patch +search-provider-simplify-solve_subprocess.patch +search-provider-cancel-the-current-process-on-new-calcula.patch +search-provider-cache-equations-avoiding-spawning-calcula.patch +search-provider-cache-only-a-limited-number-of-equations.patch +ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch diff --git a/debian/patches/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch b/debian/patches/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch new file mode 100644 index 0000000..77939ec --- /dev/null +++ b/debian/patches/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch @@ -0,0 +1,118 @@ +From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <m...@3v1n0.net> +Date: Tue, 28 Aug 2018 04:12:20 +0200 +Subject: search-provider: Cancel operations on XUbuntuCancel + +Stop process and any computation on XUbuntuCancel method, if the caller +was the same triggering the last operation. + +Fixes LP: #1756826 + +Bug-Ubuntu: https://launchpad.net/bugs/1756826 +Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183 +Forwarded: not-needed +--- + search-provider/search-provider.vala | 46 ++++++++++++++++++++++++++++++++---- + 1 file changed, 41 insertions(+), 5 deletions(-) + +diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala +index fc72128..b7c869d 100644 +--- a/search-provider/search-provider.vala ++++ b/search-provider/search-provider.vala +@@ -10,11 +10,33 @@ + * license. + */ + ++public class CallerTracker : Object ++{ ++ public BusName? bus { get; set; } ++} ++ ++public class Caller ++{ ++ private CallerTracker caller_tracker; ++ ++ public Caller (CallerTracker c, BusName sender) ++ { ++ caller_tracker = c; ++ caller_tracker.bus = sender; ++ } ++ ++ ~Caller () ++ { ++ caller_tracker.bus = null; ++ } ++} ++ + [DBus (name = "org.gnome.Shell.SearchProvider2")] + public class SearchProvider : Object + { + private unowned SearchProviderApp application; + private Cancellable cancellable; ++ private CallerTracker caller_tracker; + + private const int MAX_CACHED_OPERATIONS = 10; + private Queue<string> queued_equations; +@@ -24,6 +46,7 @@ public class SearchProvider : Object + { + application = app; + ++ caller_tracker = new CallerTracker (); + queued_equations = new Queue<string> (); + cached_equations = new HashTable<string, string> (str_hash, str_equal); + } +@@ -128,8 +151,10 @@ public class SearchProvider : Object + return true; + } + +- private async string[] get_result_identifier (string[] terms) ++ private async string[] get_result_identifier (string[] terms, GLib.BusName sender) + { ++ var owner = new Caller (caller_tracker, sender); (void) owner; ++ + /* We have at most one result: the search terms as one string */ + var equation = terms_to_equation (terms); + if (yield solve_equation (equation)) +@@ -138,14 +163,14 @@ public class SearchProvider : Object + return new string[0]; + } + +- public async string[] get_initial_result_set (string[] terms) ++ public async string[] get_initial_result_set (string[] terms, GLib.BusName sender) + { +- return yield get_result_identifier (terms); ++ return yield get_result_identifier (terms, sender); + } + +- public async string[] get_subsearch_result_set (string[] previous_results, string[] terms) ++ public async string[] get_subsearch_result_set (string[] previous_results, string[] terms, GLib.BusName sender) + { +- return yield get_result_identifier (terms); ++ return yield get_result_identifier (terms, sender); + } + + public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender) +@@ -154,6 +179,8 @@ public class SearchProvider : Object + string equation; + string result; + ++ var owner = new Caller (caller_tracker, sender); (void) owner; ++ + equation = terms_to_equation (results); + + if (!yield solve_equation (equation)) +@@ -171,6 +198,15 @@ public class SearchProvider : Object + return metadata; + } + ++ public async void x_ubuntu_cancel (BusName sender) ++ { ++ if (caller_tracker.bus == sender) ++ { ++ debug ("Cancelling Request"); ++ cancel (); ++ } ++ } ++ + private static void spawn_and_display_equation (string[] terms) + { + try
-- ubuntu-desktop mailing list ubuntu-desktop@lists.ubuntu.com https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop