Merge ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic-xubuntu-cancel-search into ~ubuntu-desktop/ubuntu/+source/gnome-calculator:ubuntu/bionic

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: 3b2a861e9c0ef946f7bbc64ead0e6411cd665e5a
Proposed branch: ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic-xubuntu-cancel-search
Merge into: ~ubuntu-desktop/ubuntu/+source/gnome-calculator:ubuntu/bionic
Prerequisite: ~3v1n0/ubuntu/+source/gnome-calculator:ubuntu/bionic
Diff against target: 1129 lines (+1026/-2)
15 files modified
debian/changelog (+28/-0)
debian/control (+2/-1)
debian/control.in (+2/-1)
debian/patches/Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.patch (+25/-0)
debian/patches/search-provider-Handle-errors-gracefully.patch (+108/-0)
debian/patches/search-provider-Use-async-calls-cancel-search-on-inactivi.patch (+233/-0)
debian/patches/search-provider-Use-lower-inactivity-timeout.patch (+30/-0)
debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch (+171/-0)
debian/patches/search-provider-cache-only-a-limited-number-of-equations.patch (+45/-0)
debian/patches/search-provider-cancel-the-current-process-on-new-calcula.patch (+30/-0)
debian/patches/search-provider-renew-inactivity-timeout-at-each-calculat.patch (+61/-0)
debian/patches/search-provider-simplify-solve_subprocess.patch (+114/-0)
debian/patches/search-provider-stop-normalizing-the-equation-twice.patch (+48/-0)
debian/patches/series (+11/-0)
debian/patches/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch (+118/-0)
Reviewer Review Type Date Requested Status
Ubuntu Desktop Pending
Review via email: mp+354335@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 44dd584..9da064b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,31 @@
1gnome-calculator (1:3.28.2-1~ubuntu18.04.3) UNRELEASED; urgency=medium
2
3 * d/p/search-provider-stop-normalizing-the-equation-twice.patch:
4 - Don't normalize multiple times an equation, fixing issues with decimal
5 numbers computations (fixes a regression introduced with previous
6 patch set in order to fix LP: #1756826)
7 * d/p/Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.patch:
8 - Fix a build issue when compiling with vala 0.40.17 (LP: #1857005)
9
10 -- Marco Trevisan (Treviño) <marco@ubuntu.com> Wed, 18 Dec 2019 21:10:54 +0100
11
12gnome-calculator (1:3.28.2-1~ubuntu18.04.2) bionic; urgency=medium
13
14 * d/p/search-provider-Use-async-calls-cancel-search-on-inactivi.patch,
15 d/p/search-provider-renew-inactivity-timeout-at-each-calculat.patch,
16 d/p/search-provider-Use-lower-inactivity-timeout.patch,
17 d/p/search-provider-simplify-solve_subprocess.patch,
18 d/p/search-provider-cache-equations-avoiding-spawning-calcula.patch,
19 d/p/search-provider-cancel-the-current-process-on-new-calcula.patch,
20 d/p/search-provider-cache-only-a-limited-number-of-equations.patch,
21 d/p/search-provider-Handle-errors-gracefully.patch,
22 d/p/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch:
23 - Make search provider async and support XUbuntuCancel method to
24 stop expensive operations that might lead to an unresponsive
25 process (LP: #1756826)
26
27 -- Marco Trevisan (Treviño) <marco@ubuntu.com> Thu, 08 Nov 2018 01:34:07 -0500
28
1gnome-calculator (1:3.28.2-1~ubuntu18.04.1) bionic; urgency=medium29gnome-calculator (1:3.28.2-1~ubuntu18.04.1) bionic; urgency=medium
230
3 * New upstream stable release (LP: #1790876)31 * New upstream stable release (LP: #1790876)
diff --git a/debian/control b/debian/control
index cd4706c..0782192 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,8 @@
5Source: gnome-calculator5Source: gnome-calculator
6Section: math6Section: math
7Priority: optional7Priority: optional
8Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>8Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
9XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
9Uploaders: Jeremy Bicha <jbicha@debian.org>, Laurent Bigonville <bigon@debian.org>, Michael Biebl <biebl@debian.org>10Uploaders: Jeremy Bicha <jbicha@debian.org>, Laurent Bigonville <bigon@debian.org>, Michael Biebl <biebl@debian.org>
10Build-Depends: appstream-util,11Build-Depends: appstream-util,
11 debhelper (>= 11.1.3),12 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 @@
1Source: gnome-calculator1Source: gnome-calculator
2Section: math2Section: math
3Priority: optional3Priority: optional
4Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
5Uploaders: @GNOME_TEAM@6Uploaders: @GNOME_TEAM@
6Build-Depends: appstream-util,7Build-Depends: appstream-util,
7 debhelper (>= 11.1.3),8 debhelper (>= 11.1.3),
diff --git a/debian/patches/Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.patch b/debian/patches/Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.patch
8new file mode 1006449new file mode 100644
index 0000000..0810e88
--- /dev/null
+++ b/debian/patches/Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.patch
@@ -0,0 +1,25 @@
1From: Rico Tzschichholz <ricotz@ubuntu.com>
2Date: Sun, 4 Nov 2018 19:41:23 +0100
3Subject: Use GLib.List.deep_copy() to fix type-argument mismatch
4
5Origin: https://gitlab.gnome.org/GNOME/gnome-calculator/commit/d89466a7
6Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-calculator/+bug/1857005
7Applied-Upstream: 3.31.2
8
9---
10 lib/equation-parser.vala | 2 +-
11 1 file changed, 1 insertion(+), 1 deletion(-)
12
13diff --git a/lib/equation-parser.vala b/lib/equation-parser.vala
14index 668e1cd..d16e5b1 100644
15--- a/lib/equation-parser.vala
16+++ b/lib/equation-parser.vala
17@@ -76,7 +76,7 @@ public class ParseNode : Object
18 public ParseNode.WithList (Parser parser, List<LexerToken> token_list, uint precedence, Associativity associativity, string? value = null)
19 {
20 this.parser = parser;
21- this.token_list = token_list.copy();
22+ this.token_list = token_list.copy_deep((CopyFunc) Object.ref);
23 this.precedence = precedence;
24 this.associativity = associativity;
25 this.value = value;
diff --git a/debian/patches/search-provider-Handle-errors-gracefully.patch b/debian/patches/search-provider-Handle-errors-gracefully.patch
0new file mode 10064426new file mode 100644
index 0000000..f78c54b
--- /dev/null
+++ b/debian/patches/search-provider-Handle-errors-gracefully.patch
@@ -0,0 +1,108 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Wed, 5 Sep 2018 17:11:27 +0200
3Subject: search-provider: Handle errors gracefully
4
5Instead of exiting immediately if a spawn error occurred, inform our dbus
6client about it with a proper spawn error.
7
8As bonus, get rid of the compile warning.
9
10Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-calculator/+bug/1795399
11Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
12Applied-Upstream: yes, 3.31.1
13---
14 search-provider/search-provider.vala | 24 +++++++++++++-----------
15 1 file changed, 13 insertions(+), 11 deletions(-)
16
17diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
18index fc72128..a48c440 100644
19--- a/search-provider/search-provider.vala
20+++ b/search-provider/search-provider.vala
21@@ -63,7 +63,7 @@ public class SearchProvider : Object
22 }
23 catch (Error e)
24 {
25- error ("Failed to spawn Calculator: %s", e.message);
26+ throw e;
27 }
28
29 if (cancellable == null)
30@@ -79,7 +79,7 @@ public class SearchProvider : Object
31 return subprocess;
32 }
33
34- private async bool solve_equation (string equation)
35+ private async bool solve_equation (string equation) throws DBusError
36 {
37 string? result;
38
39@@ -112,7 +112,8 @@ public class SearchProvider : Object
40 }
41 catch (SpawnError e)
42 {
43- error ("Failed to spawn Calculator: %s", e.message);
44+ critical ("Failed to spawn Calculator: %s", e.message);
45+ throw new DBusError.SPAWN_FAILED (e.message);
46 }
47 catch (Error e)
48 {
49@@ -128,7 +129,7 @@ public class SearchProvider : Object
50 return true;
51 }
52
53- private async string[] get_result_identifier (string[] terms)
54+ private async string[] get_result_identifier (string[] terms) throws Error
55 {
56 /* We have at most one result: the search terms as one string */
57 var equation = terms_to_equation (terms);
58@@ -138,17 +139,17 @@ public class SearchProvider : Object
59 return new string[0];
60 }
61
62- public async string[] get_initial_result_set (string[] terms)
63+ public async string[] get_initial_result_set (string[] terms) throws Error
64 {
65 return yield get_result_identifier (terms);
66 }
67
68- public async string[] get_subsearch_result_set (string[] previous_results, string[] terms)
69+ public async string[] get_subsearch_result_set (string[] previous_results, string[] terms) throws Error
70 {
71 return yield get_result_identifier (terms);
72 }
73
74- public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender)
75+ public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender) throws Error
76 requires (results.length == 1)
77 {
78 string equation;
79@@ -171,7 +172,7 @@ public class SearchProvider : Object
80 return metadata;
81 }
82
83- private static void spawn_and_display_equation (string[] terms)
84+ private static void spawn_and_display_equation (string[] terms) throws Error
85 {
86 try
87 {
88@@ -180,16 +181,17 @@ public class SearchProvider : Object
89 }
90 catch (SpawnError e)
91 {
92- error ("Failed to spawn Calculator: %s", e.message);
93+ critical ("Failed to spawn Calculator: %s", e.message);
94+ throw new DBusError.SPAWN_FAILED (e.message);
95 }
96 }
97
98- public void activate_result (string result, string[] terms, uint32 timestamp)
99+ public void activate_result (string result, string[] terms, uint32 timestamp) throws Error
100 {
101 spawn_and_display_equation (terms);
102 }
103
104- public void launch_search (string[] terms, uint32 timestamp)
105+ public void launch_search (string[] terms, uint32 timestamp) throws Error
106 {
107 spawn_and_display_equation (terms);
108 }
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
0new file mode 100644109new file mode 100644
index 0000000..d8e38be
--- /dev/null
+++ b/debian/patches/search-provider-Use-async-calls-cancel-search-on-inactivi.patch
@@ -0,0 +1,233 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 24 Aug 2018 06:57:03 +0200
3Subject: search-provider: Use async calls, cancel search on inactivity
4
5Move to async methods everywhere and factorize the `solve` calls to a single
6method that only uses Subprocess and that can be cancelled.
7
8As per this, if the the search-provider is trying to compute some complex
9operation, the daemon won't hang and once the applications' inactivity
10timeout is hit, any running instance of gnome-calculator will be killed and
11the daemon will return accordingly.
12
13This reduces the impact of an issue that can cause gnome-calculator to keep
14running forever if a complex computation is required (10!!!) from the shell,
15and won't ever be killed (see GNOME/gnome-shell#183).
16
17This is also a prerequisite for supporting the search Cancellation that is
18going to be available on next version of the Search provider protocol
19(as per GNOME/gnome-shell#436)
20
21Bug-Ubuntu: https://launchpad.net/bugs/1756826
22Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
23Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
24Applied-Upstream: yes, 3.31.1
25---
26 search-provider/search-provider.vala | 126 +++++++++++++++++++++++++----------
27 1 file changed, 89 insertions(+), 37 deletions(-)
28
29diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
30index 26c72af..659f73d 100644
31--- a/search-provider/search-provider.vala
32+++ b/search-provider/search-provider.vala
33@@ -1,6 +1,7 @@
34 /* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
35 *
36 * Copyright (C) 2014 Michael Catanzaro
37+ * Copyright (C) 2018 Marco Trevisan
38 *
39 * This program is free software: you can redistribute it and/or modify it under
40 * the terms of the GNU General Public License as published by the Free Software
41@@ -12,17 +13,85 @@
42 [DBus (name = "org.gnome.Shell.SearchProvider2")]
43 public class SearchProvider : Object
44 {
45+ private Cancellable cancellable = new Cancellable ();
46+
47+ ~SearchProvider ()
48+ {
49+ cancel ();
50+ }
51+
52+ [DBus (visible = false)]
53+ public void cancel ()
54+ {
55+ if (cancellable != null)
56+ {
57+ cancellable.cancel ();
58+ }
59+ }
60+
61 private static string terms_to_equation (string[] terms)
62 {
63 return string.joinv (" ", terms);
64 }
65
66- private static bool can_parse (string[] terms)
67+ private async Subprocess solve_subprocess (string equation, bool return_solution = false, out string? solution_buf = null) throws Error
68 {
69+ Subprocess subprocess;
70+ string[] argv = {"gnome-calculator", "--solve"};
71+ argv += equation;
72+ argv += null;
73+
74+ debug (@"Trying to solve $(equation)");
75+
76 try
77 {
78- int exit_status;
79+ // Eat output so that it doesn't wind up in the journal. It's
80+ // expected that most searches are not valid calculator input.
81+ var flags = SubprocessFlags.STDERR_PIPE;
82+
83+ if (return_solution)
84+ {
85+ flags |= SubprocessFlags.STDOUT_PIPE;
86+ }
87+
88+ subprocess = new Subprocess.newv (argv, flags);
89+ }
90+ catch (Error e)
91+ {
92+ error ("Failed to spawn Calculator: %s", e.message);
93+ }
94+
95+ try
96+ {
97+ string stderr_buf;
98+
99+ cancellable = new Cancellable ();
100+ cancellable.cancelled.connect (() => {
101+ subprocess.force_exit ();
102+ cancellable = null;
103+ });
104+
105+ yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf);
106+ }
107+ catch (Error e)
108+ {
109+ if (e is IOError.CANCELLED)
110+ {
111+ throw e;
112+ }
113+ else
114+ {
115+ error ("Failed reading result: %s", e.message);
116+ }
117+ }
118
119+ return subprocess;
120+ }
121+
122+ private async bool can_parse (string[] terms)
123+ {
124+ try
125+ {
126 var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP);
127 if (tsep_string == null || tsep_string == "")
128 tsep_string = " ";
129@@ -39,14 +108,8 @@ public class SearchProvider : Object
130 return false;
131 }
132
133- // Eat output so that it doesn't wind up in the journal. It's
134- // expected that most searches are not valid calculator input.
135- string stdout_buf;
136- string stderr_buf;
137- Process.spawn_command_line_sync (
138- "gnome-calculator --solve " + Shell.quote (equation),
139- out stdout_buf, out stderr_buf, out exit_status);
140- Process.check_exit_status (exit_status);
141+ var subprocess = yield solve_subprocess (equation);
142+ yield subprocess.wait_check_async ();
143 }
144 catch (SpawnError e)
145 {
146@@ -60,54 +123,37 @@ public class SearchProvider : Object
147 return true;
148 }
149
150- private static string[] get_result_identifier (string[] terms)
151- ensures (result.length == 0 || result.length == 1)
152+ private async string[] get_result_identifier (string[] terms)
153 {
154 /* We have at most one result: the search terms as one string */
155- if (can_parse (terms))
156+ if (yield can_parse (terms))
157 return { terms_to_equation (terms) };
158 else
159 return new string[0];
160 }
161
162- public string[] get_initial_result_set (string[] terms)
163+ public async string[] get_initial_result_set (string[] terms)
164 {
165- return get_result_identifier (terms);
166+ return yield get_result_identifier (terms);
167 }
168
169- public string[] get_subsearch_result_set (string[] previous_results, string[] terms)
170+ public async string[] get_subsearch_result_set (string[] previous_results, string[] terms)
171 {
172- return get_result_identifier (terms);
173+ return yield get_result_identifier (terms);
174 }
175
176- public HashTable<string, Variant>[] get_result_metas (string[] results)
177+ public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender)
178 requires (results.length == 1)
179- ensures (result.length == 1)
180 {
181- Subprocess subprocess;
182 string stdout_buf;
183- string stderr_buf;
184-
185- string[] argv = {"gnome-calculator", "--solve"};
186- argv += results[0];
187- argv += null;
188-
189- try
190- {
191- subprocess = new Subprocess.newv (argv, SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_PIPE);
192- }
193- catch (Error e)
194- {
195- error ("Failed to spawn Calculator: %s", e.message);
196- }
197
198 try
199 {
200- subprocess.communicate_utf8 (null, null, out stdout_buf, out stderr_buf);
201+ yield solve_subprocess (results[0], true, out stdout_buf);
202 }
203 catch (Error e)
204 {
205- error ("Failed reading result: %s", e.message);
206+ return new HashTable<string, Variant>[0];
207 }
208
209 var metadata = new HashTable<string, Variant>[1];
210@@ -155,9 +201,11 @@ public class SearchProviderApp : Application
211
212 public override bool dbus_register (DBusConnection connection, string object_path)
213 {
214+ SearchProvider search_provider = new SearchProvider ();
215+
216 try
217 {
218- connection.register_object (object_path, new SearchProvider ());
219+ connection.register_object (object_path, search_provider);
220 }
221 catch (IOError error)
222 {
223@@ -165,6 +213,10 @@ public class SearchProviderApp : Application
224 quit ();
225 }
226
227+ shutdown.connect (() => {
228+ search_provider.cancel ();
229+ });
230+
231 return true;
232 }
233 }
diff --git a/debian/patches/search-provider-Use-lower-inactivity-timeout.patch b/debian/patches/search-provider-Use-lower-inactivity-timeout.patch
0new file mode 100644234new file mode 100644
index 0000000..5008fe5
--- /dev/null
+++ b/debian/patches/search-provider-Use-lower-inactivity-timeout.patch
@@ -0,0 +1,30 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 24 Aug 2018 07:12:12 +0200
3Subject: search-provider: Use lower inactivity timeout
4
5Since we're renewing it at every call involving a process call, we can just
6set it to a lower value than the default dbus proxy timeout, so that the provider
7will return invalid values before that the timeout has been hit.
8
9Bug-Ubuntu: https://launchpad.net/bugs/1756826
10Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
11Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
12Applied-Upstream: yes, 3.31.1
13---
14 search-provider/search-provider.vala | 3 ++-
15 1 file changed, 2 insertions(+), 1 deletion(-)
16
17diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
18index 7e54fa6..9035c58 100644
19--- a/search-provider/search-provider.vala
20+++ b/search-provider/search-provider.vala
21@@ -203,7 +203,8 @@ public class SearchProviderApp : Application
22 {
23 Object (application_id: "org.gnome.Calculator.SearchProvider",
24 flags: ApplicationFlags.IS_SERVICE,
25- inactivity_timeout: 60000);
26+ inactivity_timeout: 20000);
27+ }
28
29 public void renew_inactivity_timeout ()
30 {
diff --git a/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch b/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch
0new file mode 10064431new file mode 100644
index 0000000..85d83ce
--- /dev/null
+++ b/debian/patches/search-provider-cache-equations-avoiding-spawning-calcula.patch
@@ -0,0 +1,171 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Mon, 27 Aug 2018 18:45:34 +0200
3Subject: search-provider: cache equations avoiding spawning calculator twice
4
5Currently we spawn the calculator two times for each operation, one to check
6if the search provider is valid for such syntax, the other time to actually
7present the results. But since these results are just available at first
8call, we can just keep them around and return them if the shell requires them.
9
10Since the search provider deamon is kept alive for just few moments, there's
11no real need to cleanup the cache using a queue.
12
13In case of multiple async calls, reuse cancellable instead so that we can
14just kill all the related processes one time at once.
15
16Bug-Ubuntu: https://launchpad.net/bugs/1756826
17Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
18Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
19Applied-Upstream: yes, 3.31.1
20---
21 search-provider/search-provider.vala | 79 ++++++++++++++++++++----------------
22 1 file changed, 45 insertions(+), 34 deletions(-)
23
24diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
25index a3c57f7..af2779e 100644
26--- a/search-provider/search-provider.vala
27+++ b/search-provider/search-provider.vala
28@@ -14,10 +14,13 @@
29 public class SearchProvider : Object
30 {
31 private unowned SearchProviderApp application;
32- private Cancellable cancellable = new Cancellable ();
33+ private Cancellable cancellable;
34+
35+ private HashTable<string, string> cached_equations;
36 public SearchProvider (SearchProviderApp app)
37 {
38 application = app;
39+ cached_equations = new HashTable<string, string> (str_hash, str_equal);
40 }
41
42 ~SearchProvider ()
43@@ -29,9 +32,7 @@ public class SearchProvider : Object
44 public void cancel ()
45 {
46 if (cancellable != null)
47- {
48 cancellable.cancel ();
49- }
50 }
51
52 private static string terms_to_equation (string[] terms)
53@@ -60,7 +61,9 @@ public class SearchProvider : Object
54 error ("Failed to spawn Calculator: %s", e.message);
55 }
56
57- cancellable = new Cancellable ();
58+ if (cancellable == null)
59+ cancellable = new Cancellable ();
60+
61 cancellable.cancelled.connect (() => {
62 subprocess.force_exit ();
63 cancellable = null;
64@@ -71,29 +74,36 @@ public class SearchProvider : Object
65 return subprocess;
66 }
67
68- private async bool can_parse (string[] terms)
69+ private async bool solve_equation (string equation)
70 {
71- try
72- {
73- var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP);
74- if (tsep_string == null || tsep_string == "")
75- tsep_string = " ";
76+ string? result;
77
78- var decimal = Posix.nl_langinfo (Posix.NLItem.RADIXCHAR);
79- if (decimal == null)
80- decimal = "";
81+ cancel();
82
83- // "normalize" input to a format known to double.try_parse
84- var equation = terms_to_equation (terms).replace (tsep_string, "").replace (decimal, ".");
85+ var tsep_string = Posix.nl_langinfo (Posix.NLItem.THOUSEP);
86+ if (tsep_string == null || tsep_string == "")
87+ tsep_string = " ";
88
89- cancel();
90+ var decimal = Posix.nl_langinfo (Posix.NLItem.RADIXCHAR);
91+ if (decimal == null)
92+ decimal = "";
93
94- // if the search is a plain number, don't process it
95- if (double.try_parse (equation)) {
96- return false;
97- }
98+ // "normalize" input to a format known to double.try_parse
99+ var normalized_equation = equation.replace (tsep_string, "").replace (decimal, ".");
100
101- (yield solve_subprocess (equation)).wait_check (cancellable);
102+ // if the search is a plain number, don't process it
103+ if (double.try_parse (normalized_equation)) {
104+ return false;
105+ }
106+
107+ if (cached_equations.lookup (equation) != null)
108+ return true;
109+
110+ try
111+ {
112+ var subprocess = yield solve_subprocess (normalized_equation);
113+ yield subprocess.communicate_utf8_async (null, cancellable, out result, null);
114+ subprocess.wait_check (cancellable);
115 }
116 catch (SpawnError e)
117 {
118@@ -104,14 +114,17 @@ public class SearchProvider : Object
119 return false;
120 }
121
122+ cached_equations.insert (equation, result.strip ());
123+
124 return true;
125 }
126
127 private async string[] get_result_identifier (string[] terms)
128 {
129 /* We have at most one result: the search terms as one string */
130- if (yield can_parse (terms))
131- return { terms_to_equation (terms) };
132+ var equation = terms_to_equation (terms);
133+ if (yield solve_equation (equation))
134+ return { equation };
135 else
136 return new string[0];
137 }
138@@ -129,24 +142,22 @@ public class SearchProvider : Object
139 public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender)
140 requires (results.length == 1)
141 {
142- string stdout_buf;
143- string stderr_buf;
144+ string equation;
145+ string result;
146
147- try
148- {
149- var subprocess = yield solve_subprocess (results[0]);
150- yield subprocess.communicate_utf8_async (null, cancellable, out stdout_buf, out stderr_buf);
151- }
152- catch (Error e)
153- {
154+ equation = terms_to_equation (results);
155+
156+ if (!yield solve_equation (equation))
157 return new HashTable<string, Variant>[0];
158- }
159+
160+ result = cached_equations.lookup (equation);
161+ assert (result != null);
162
163 var metadata = new HashTable<string, Variant>[1];
164 metadata[0] = new HashTable<string, Variant>(str_hash, str_equal);
165 metadata[0].insert ("id", results[0]);
166 metadata[0].insert ("name", results[0] );
167- metadata[0].insert ("description", " = " + stdout_buf.strip ());
168+ metadata[0].insert ("description", @" = $result");
169
170 return metadata;
171 }
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
0new file mode 100644172new file mode 100644
index 0000000..651aa28
--- /dev/null
+++ b/debian/patches/search-provider-cache-only-a-limited-number-of-equations.patch
@@ -0,0 +1,45 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Mon, 27 Aug 2018 18:56:09 +0200
3Subject: search-provider: cache only a limited number of equations
4
5Bug-Ubuntu: https://launchpad.net/bugs/1756826
6Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
7Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
8Applied-Upstream: yes, 3.31.1
9---
10 search-provider/search-provider.vala | 9 +++++++++
11 1 file changed, 9 insertions(+)
12
13diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
14index af2779e..fc72128 100644
15--- a/search-provider/search-provider.vala
16+++ b/search-provider/search-provider.vala
17@@ -16,10 +16,15 @@ public class SearchProvider : Object
18 private unowned SearchProviderApp application;
19 private Cancellable cancellable;
20
21+ private const int MAX_CACHED_OPERATIONS = 10;
22+ private Queue<string> queued_equations;
23 private HashTable<string, string> cached_equations;
24+
25 public SearchProvider (SearchProviderApp app)
26 {
27 application = app;
28+
29+ queued_equations = new Queue<string> ();
30 cached_equations = new HashTable<string, string> (str_hash, str_equal);
31 }
32
33@@ -114,8 +119,12 @@ public class SearchProvider : Object
34 return false;
35 }
36
37+ queued_equations.push_tail (equation);
38 cached_equations.insert (equation, result.strip ());
39
40+ if (queued_equations.length > MAX_CACHED_OPERATIONS)
41+ cached_equations.remove (queued_equations.pop_head ());
42+
43 return true;
44 }
45
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
0new file mode 10064446new file mode 100644
index 0000000..26435e2
--- /dev/null
+++ b/debian/patches/search-provider-cancel-the-current-process-on-new-calcula.patch
@@ -0,0 +1,30 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Thu, 30 Aug 2018 18:47:16 +0200
3Subject: search-provider: cancel the current process on new calculation
4 request
5
6As there's just one shell running at time, there's no point of supporting
7parallel calls, we can just safely refer to the last equation as the only one
8we need to compute.
9
10Bug-Ubuntu: https://launchpad.net/bugs/1756826
11Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
12Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
13Applied-Upstream: yes, 3.31.1
14---
15 search-provider/search-provider.vala | 2 ++
16 1 file changed, 2 insertions(+)
17
18diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
19index df37b86..a3c57f7 100644
20--- a/search-provider/search-provider.vala
21+++ b/search-provider/search-provider.vala
22@@ -86,6 +86,8 @@ public class SearchProvider : Object
23 // "normalize" input to a format known to double.try_parse
24 var equation = terms_to_equation (terms).replace (tsep_string, "").replace (decimal, ".");
25
26+ cancel();
27+
28 // if the search is a plain number, don't process it
29 if (double.try_parse (equation)) {
30 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
0new file mode 10064431new file mode 100644
index 0000000..274aae1
--- /dev/null
+++ b/debian/patches/search-provider-renew-inactivity-timeout-at-each-calculat.patch
@@ -0,0 +1,61 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 24 Aug 2018 07:10:17 +0200
3Subject: search-provider: renew inactivity timeout at each calculator run
4
5As per the async rewrite, now the daemon inactivity timeout might happen
6when another call has just been done, while we don't want this to be the case.
7
8So, everytime we do a subprocess call, let's renew the application timeout.
9
10Bug-Ubuntu: https://launchpad.net/bugs/1756826
11Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
12Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/100
13Applied-Upstream: yes, 3.31.1
14---
15 search-provider/search-provider.vala | 14 +++++++++++++-
16 1 file changed, 13 insertions(+), 1 deletion(-)
17
18diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
19index 659f73d..7e54fa6 100644
20--- a/search-provider/search-provider.vala
21+++ b/search-provider/search-provider.vala
22@@ -13,7 +13,12 @@
23 [DBus (name = "org.gnome.Shell.SearchProvider2")]
24 public class SearchProvider : Object
25 {
26+ private unowned SearchProviderApp application;
27 private Cancellable cancellable = new Cancellable ();
28+ public SearchProvider (SearchProviderApp app)
29+ {
30+ application = app;
31+ }
32
33 ~SearchProvider ()
34 {
35@@ -71,6 +76,8 @@ public class SearchProvider : Object
36 cancellable = null;
37 });
38
39+ application.renew_inactivity_timeout ();
40+
41 yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf);
42 }
43 catch (Error e)
44@@ -197,11 +204,16 @@ public class SearchProviderApp : Application
45 Object (application_id: "org.gnome.Calculator.SearchProvider",
46 flags: ApplicationFlags.IS_SERVICE,
47 inactivity_timeout: 60000);
48+
49+ public void renew_inactivity_timeout ()
50+ {
51+ this.hold ();
52+ this.release ();
53 }
54
55 public override bool dbus_register (DBusConnection connection, string object_path)
56 {
57- SearchProvider search_provider = new SearchProvider ();
58+ SearchProvider search_provider = new SearchProvider (this);
59
60 try
61 {
diff --git a/debian/patches/search-provider-simplify-solve_subprocess.patch b/debian/patches/search-provider-simplify-solve_subprocess.patch
0new file mode 10064462new file mode 100644
index 0000000..4f9cde8
--- /dev/null
+++ b/debian/patches/search-provider-simplify-solve_subprocess.patch
@@ -0,0 +1,114 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Fri, 24 Aug 2018 07:31:37 +0200
3Subject: search-provider: simplify solve_subprocess
4
5Only return a subprocess in solve_subprocess and make the callers deal with
6the actual operation to perform.
7
8Bug-Ubuntu: https://launchpad.net/bugs/1756826
9Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
10Forwarded: https://gitlab.gnome.org/GNOME/gnome-calculator/merge_requests/10
11Applied-Upstream: yes, 3.31.1
12---
13 search-provider/search-provider.vala | 49 ++++++++++--------------------------
14 1 file changed, 13 insertions(+), 36 deletions(-)
15
16diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
17index 9035c58..df37b86 100644
18--- a/search-provider/search-provider.vala
19+++ b/search-provider/search-provider.vala
20@@ -39,7 +39,7 @@ public class SearchProvider : Object
21 return string.joinv (" ", terms);
22 }
23
24- private async Subprocess solve_subprocess (string equation, bool return_solution = false, out string? solution_buf = null) throws Error
25+ private async Subprocess solve_subprocess (string equation) throws Error
26 {
27 Subprocess subprocess;
28 string[] argv = {"gnome-calculator", "--solve"};
29@@ -52,13 +52,7 @@ public class SearchProvider : Object
30 {
31 // Eat output so that it doesn't wind up in the journal. It's
32 // expected that most searches are not valid calculator input.
33- var flags = SubprocessFlags.STDERR_PIPE;
34-
35- if (return_solution)
36- {
37- flags |= SubprocessFlags.STDOUT_PIPE;
38- }
39-
40+ var flags = SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_PIPE;
41 subprocess = new Subprocess.newv (argv, flags);
42 }
43 catch (Error e)
44@@ -66,31 +60,13 @@ public class SearchProvider : Object
45 error ("Failed to spawn Calculator: %s", e.message);
46 }
47
48- try
49- {
50- string stderr_buf;
51-
52- cancellable = new Cancellable ();
53- cancellable.cancelled.connect (() => {
54- subprocess.force_exit ();
55- cancellable = null;
56- });
57-
58- application.renew_inactivity_timeout ();
59+ cancellable = new Cancellable ();
60+ cancellable.cancelled.connect (() => {
61+ subprocess.force_exit ();
62+ cancellable = null;
63+ });
64
65- yield subprocess.communicate_utf8_async (null, cancellable, out solution_buf, out stderr_buf);
66- }
67- catch (Error e)
68- {
69- if (e is IOError.CANCELLED)
70- {
71- throw e;
72- }
73- else
74- {
75- error ("Failed reading result: %s", e.message);
76- }
77- }
78+ application.renew_inactivity_timeout ();
79
80 return subprocess;
81 }
82@@ -115,8 +91,7 @@ public class SearchProvider : Object
83 return false;
84 }
85
86- var subprocess = yield solve_subprocess (equation);
87- yield subprocess.wait_check_async ();
88+ (yield solve_subprocess (equation)).wait_check (cancellable);
89 }
90 catch (SpawnError e)
91 {
92@@ -153,10 +128,12 @@ public class SearchProvider : Object
93 requires (results.length == 1)
94 {
95 string stdout_buf;
96+ string stderr_buf;
97
98 try
99 {
100- yield solve_subprocess (results[0], true, out stdout_buf);
101+ var subprocess = yield solve_subprocess (results[0]);
102+ yield subprocess.communicate_utf8_async (null, cancellable, out stdout_buf, out stderr_buf);
103 }
104 catch (Error e)
105 {
106@@ -167,7 +144,7 @@ public class SearchProvider : Object
107 metadata[0] = new HashTable<string, Variant>(str_hash, str_equal);
108 metadata[0].insert ("id", results[0]);
109 metadata[0].insert ("name", results[0] );
110- metadata[0].insert ("description", " = " + stdout_buf.strip() );
111+ metadata[0].insert ("description", " = " + stdout_buf.strip ());
112
113 return metadata;
114 }
diff --git a/debian/patches/search-provider-stop-normalizing-the-equation-twice.patch b/debian/patches/search-provider-stop-normalizing-the-equation-twice.patch
0new file mode 100644115new file mode 100644
index 0000000..6882583
--- /dev/null
+++ b/debian/patches/search-provider-stop-normalizing-the-equation-twice.patch
@@ -0,0 +1,48 @@
1From: Pascal Nowack <Pascal.Nowack@gmx.de>
2Date: Sun, 31 Mar 2019 14:11:16 +0200
3Subject: search-provider: stop normalizing the equation twice
4
5When an equation is given by the g-s overview, g-c
6will solve this equation, where it will be first
7normalized and then solved.
8This is done by running a subprocess, where g-c
9will call g-c in this subprocess with the
10"--solve" argument.
11With this "--solve" argument, the equation will
12also be normalized.
13However, when an equation is given by the g-s
14overview, it will also be normalized in a check,
15that happens before the solve process, to not to
16process single numbers given by the g-s overview.
17This normalized equation will then be used to
18invoke the subprocess to solve the equation,
19leading into normalizing the already normalized
20equation and therefore resulting into wrong
21results when the equation itself contains
22decimal numbers.
23
24Solve this issue, by invoking the subprocess with
25the unnormalized equation, instead of the
26normalized one, to not to normalize the
27equation twice.
28
29Closes: https://gitlab.gnome.org/GNOME/gnome-calculator/issues/104
30
31Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/104
32---
33 search-provider/search-provider.vala | 2 +-
34 1 file changed, 1 insertion(+), 1 deletion(-)
35
36diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
37index 9823ef7..7f9f51e 100644
38--- a/search-provider/search-provider.vala
39+++ b/search-provider/search-provider.vala
40@@ -129,7 +129,7 @@ public class SearchProvider : Object
41
42 try
43 {
44- var subprocess = yield solve_subprocess (normalized_equation);
45+ var subprocess = yield solve_subprocess (equation);
46 yield subprocess.communicate_utf8_async (null, cancellable, out result, null);
47 subprocess.wait_check (cancellable);
48 }
diff --git a/debian/patches/series b/debian/patches/series
index e69de29..f088177 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -0,0 +1,11 @@
1search-provider-Use-async-calls-cancel-search-on-inactivi.patch
2search-provider-renew-inactivity-timeout-at-each-calculat.patch
3search-provider-Use-lower-inactivity-timeout.patch
4search-provider-simplify-solve_subprocess.patch
5search-provider-cancel-the-current-process-on-new-calcula.patch
6search-provider-cache-equations-avoiding-spawning-calcula.patch
7search-provider-cache-only-a-limited-number-of-equations.patch
8search-provider-Handle-errors-gracefully.patch
9ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch
10search-provider-stop-normalizing-the-equation-twice.patch
11Use-GLib.List.deep_copy-to-fix-type-argument-mismatch.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
0new file mode 10064412new file mode 100644
index 0000000..edc9419
--- /dev/null
+++ b/debian/patches/ubuntu/search-provider-Cancel-operations-on-XUbuntuCancel.patch
@@ -0,0 +1,118 @@
1From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
2Date: Tue, 28 Aug 2018 04:12:20 +0200
3Subject: search-provider: Cancel operations on XUbuntuCancel
4
5Stop process and any computation on XUbuntuCancel method, if the caller
6was the same triggering the last operation.
7
8Fixes LP: #1756826
9
10Bug-Ubuntu: https://launchpad.net/bugs/1756826
11Bug-GNOME: https://gitlab.gnome.org/GNOME/gnome-shell/issues/183
12Forwarded: not-needed
13---
14 search-provider/search-provider.vala | 46 ++++++++++++++++++++++++++++++++----
15 1 file changed, 41 insertions(+), 5 deletions(-)
16
17diff --git a/search-provider/search-provider.vala b/search-provider/search-provider.vala
18index a48c440..9823ef7 100644
19--- a/search-provider/search-provider.vala
20+++ b/search-provider/search-provider.vala
21@@ -10,11 +10,33 @@
22 * license.
23 */
24
25+public class CallerTracker : Object
26+{
27+ public BusName? bus { get; set; }
28+}
29+
30+public class Caller
31+{
32+ private CallerTracker caller_tracker;
33+
34+ public Caller (CallerTracker c, BusName sender)
35+ {
36+ caller_tracker = c;
37+ caller_tracker.bus = sender;
38+ }
39+
40+ ~Caller ()
41+ {
42+ caller_tracker.bus = null;
43+ }
44+}
45+
46 [DBus (name = "org.gnome.Shell.SearchProvider2")]
47 public class SearchProvider : Object
48 {
49 private unowned SearchProviderApp application;
50 private Cancellable cancellable;
51+ private CallerTracker caller_tracker;
52
53 private const int MAX_CACHED_OPERATIONS = 10;
54 private Queue<string> queued_equations;
55@@ -24,6 +46,7 @@ public class SearchProvider : Object
56 {
57 application = app;
58
59+ caller_tracker = new CallerTracker ();
60 queued_equations = new Queue<string> ();
61 cached_equations = new HashTable<string, string> (str_hash, str_equal);
62 }
63@@ -129,8 +152,10 @@ public class SearchProvider : Object
64 return true;
65 }
66
67- private async string[] get_result_identifier (string[] terms) throws Error
68+ private async string[] get_result_identifier (string[] terms, GLib.BusName sender) throws Error
69 {
70+ var owner = new Caller (caller_tracker, sender); (void) owner;
71+
72 /* We have at most one result: the search terms as one string */
73 var equation = terms_to_equation (terms);
74 if (yield solve_equation (equation))
75@@ -139,14 +164,14 @@ public class SearchProvider : Object
76 return new string[0];
77 }
78
79- public async string[] get_initial_result_set (string[] terms) throws Error
80+ public async string[] get_initial_result_set (string[] terms, GLib.BusName sender) throws Error
81 {
82- return yield get_result_identifier (terms);
83+ return yield get_result_identifier (terms, sender);
84 }
85
86- public async string[] get_subsearch_result_set (string[] previous_results, string[] terms) throws Error
87+ public async string[] get_subsearch_result_set (string[] previous_results, string[] terms, GLib.BusName sender) throws Error
88 {
89- return yield get_result_identifier (terms);
90+ return yield get_result_identifier (terms, sender);
91 }
92
93 public async HashTable<string, Variant>[] get_result_metas (string[] results, GLib.BusName sender) throws Error
94@@ -155,6 +180,8 @@ public class SearchProvider : Object
95 string equation;
96 string result;
97
98+ var owner = new Caller (caller_tracker, sender); (void) owner;
99+
100 equation = terms_to_equation (results);
101
102 if (!yield solve_equation (equation))
103@@ -172,6 +199,15 @@ public class SearchProvider : Object
104 return metadata;
105 }
106
107+ public async void x_ubuntu_cancel (BusName sender)
108+ {
109+ if (caller_tracker.bus == sender)
110+ {
111+ debug ("Cancelling Request");
112+ cancel ();
113+ }
114+ }
115+
116 private static void spawn_and_display_equation (string[] terms) throws Error
117 {
118 try

Subscribers

People subscribed via source and target branches