Merge lp:~psusi/ubuntu/utopic/gparted/fix-crashes into lp:ubuntu/utopic/gparted
- Utopic (14.10)
- fix-crashes
- Merge into utopic
Proposed by
Phillip Susi
Status: | Merged |
---|---|
Merge reported by: | Brian Murray |
Merged at revision: | not available |
Proposed branch: | lp:~psusi/ubuntu/utopic/gparted/fix-crashes |
Merge into: | lp:ubuntu/utopic/gparted |
Diff against target: |
485 lines (+390/-11) 8 files modified
.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/include/PipeCapture.h (+49/-0) .pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/src/PipeCapture.cc (+111/-0) .pc/applied-patches (+1/-0) debian/changelog (+8/-0) debian/patches/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch (+215/-0) debian/patches/series (+1/-0) include/PipeCapture.h (+0/-1) src/PipeCapture.cc (+5/-10) |
To merge this branch: | bzr merge lp:~psusi/ubuntu/utopic/gparted/fix-crashes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brian Murray | Approve | ||
Review via email: mp+240273@code.launchpad.net |
Commit message
Description of the change
Backport of an upstream fix of a cross thread write after free that causes erratic behavior and crashes.
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
1 | === added directory '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch' |
2 | === added file '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/.timestamp' |
3 | === added directory '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/include' |
4 | === added file '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/include/PipeCapture.h' |
5 | --- .pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/include/PipeCapture.h 1970-01-01 00:00:00 +0000 |
6 | +++ .pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/include/PipeCapture.h 2014-10-31 14:25:19 +0000 |
7 | @@ -0,0 +1,49 @@ |
8 | +/* Copyright (C) 2013 Phillip Susi |
9 | + * |
10 | + * This program is free software; you can redistribute it and/or modify |
11 | + * it under the terms of the GNU General Public License as published by |
12 | + * the Free Software Foundation; either version 2 of the License, or |
13 | + * (at your option) any later version. |
14 | + * |
15 | + * This program is distributed in the hope that it will be useful, |
16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | + * GNU General Public License for more details. |
19 | + * |
20 | + * You should have received a copy of the GNU General Public License |
21 | + * along with this program; if not, see <http://www.gnu.org/licenses/>. |
22 | + */ |
23 | + |
24 | +#ifndef GPARTED_PIPECAPTURE_H |
25 | +#define GPARTED_PIPECAPTURE_H |
26 | + |
27 | +#include <glibmm/ustring.h> |
28 | +#include <glibmm/main.h> |
29 | +#include <glibmm/iochannel.h> |
30 | + |
31 | +namespace GParted { |
32 | + |
33 | +// captures output pipe of subprocess into a ustring and emits a signal on eof |
34 | +class PipeCapture |
35 | +{ |
36 | + Glib::ustring &buff; |
37 | + Glib::ustring::size_type linestart ; |
38 | + Glib::ustring::size_type cursor ; |
39 | + Glib::ustring::size_type lineend ; |
40 | + Glib::RefPtr<Glib::IOChannel> channel; |
41 | + guint sourceid; |
42 | + bool OnReadable( Glib::IOCondition condition ); |
43 | + static gboolean _OnReadable( GIOChannel *source, |
44 | + GIOCondition condition, |
45 | + gpointer data ); |
46 | +public: |
47 | + PipeCapture( int fd, Glib::ustring &buffer ); |
48 | + void connect_signal(); |
49 | + ~PipeCapture(); |
50 | + sigc::signal<void> signal_eof; |
51 | + sigc::signal<void> signal_update; |
52 | +}; |
53 | + |
54 | +} // namepace GParted |
55 | + |
56 | +#endif /* GPARTED_PIPECAPTURE_H */ |
57 | |
58 | === added directory '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/src' |
59 | === added file '.pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/src/PipeCapture.cc' |
60 | --- .pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/src/PipeCapture.cc 1970-01-01 00:00:00 +0000 |
61 | +++ .pc/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch/src/PipeCapture.cc 2014-10-31 14:25:19 +0000 |
62 | @@ -0,0 +1,111 @@ |
63 | +/* Copyright (C) 2013 Phillip Susi |
64 | + * |
65 | + * This program is free software; you can redistribute it and/or modify |
66 | + * it under the terms of the GNU General Public License as published by |
67 | + * the Free Software Foundation; either version 2 of the License, or |
68 | + * (at your option) any later version. |
69 | + * |
70 | + * This program is distributed in the hope that it will be useful, |
71 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
72 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
73 | + * GNU General Public License for more details. |
74 | + * |
75 | + * You should have received a copy of the GNU General Public License |
76 | + * along with this program; if not, see <http://www.gnu.org/licenses/>. |
77 | + */ |
78 | + |
79 | +#include "../include/PipeCapture.h" |
80 | +#include <iostream> |
81 | + |
82 | +namespace GParted { |
83 | + |
84 | +PipeCapture::PipeCapture( int fd, Glib::ustring &string ) : buff( string ), |
85 | + linestart( 0 ), cursor( 0 ), lineend( 0 ), |
86 | + sourceid( 0 ) |
87 | +{ |
88 | + // tie fd to string |
89 | + // make channel |
90 | + channel = Glib::IOChannel::create_from_fd( fd ); |
91 | +} |
92 | + |
93 | +void PipeCapture::connect_signal() |
94 | +{ |
95 | + // connect handler to signal input/output |
96 | + sourceid = g_io_add_watch( channel->gobj(), |
97 | + GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP), |
98 | + _OnReadable, |
99 | + this ); |
100 | +} |
101 | + |
102 | +gboolean PipeCapture::_OnReadable( GIOChannel *source, |
103 | + GIOCondition condition, |
104 | + gpointer data ) |
105 | +{ |
106 | + PipeCapture *pc = static_cast<PipeCapture *>(data); |
107 | + gboolean rc = pc->OnReadable( Glib::IOCondition(condition) ); |
108 | + if (!rc) |
109 | + pc->sourceid = 0; |
110 | + return rc; |
111 | +} |
112 | + |
113 | + |
114 | +bool PipeCapture::OnReadable( Glib::IOCondition condition ) |
115 | +{ |
116 | + //Read from pipe and store in buff. Provide minimal interpretation so |
117 | + // programs which use text progress bars are displayed correctly. |
118 | + // Linestart, cursor and lineend are offsets into buff like this: |
119 | + // "Previous line\n |
120 | + // Current line. Text progress bar: XXXXXXXXXX----------" |
121 | + // ^ ^ ^ |
122 | + // linestart cursor lineend |
123 | + Glib::ustring str; |
124 | + Glib::IOStatus status = channel->read( str, 512 ); |
125 | + if (status == Glib::IO_STATUS_NORMAL) |
126 | + { |
127 | + for( Glib::ustring::iterator s = str.begin(); s != str.end(); s++ ) |
128 | + { |
129 | + if( *s == '\b' ) { |
130 | + if ( cursor > linestart ) |
131 | + cursor -- ; |
132 | + } |
133 | + else if( *s == '\r' ) |
134 | + cursor = linestart ; |
135 | + else if( *s == '\n' ) { |
136 | + cursor = lineend ; |
137 | + buff .append( 1, '\n' ) ; |
138 | + cursor ++ ; |
139 | + linestart = cursor ; |
140 | + lineend = cursor ; |
141 | + } |
142 | + else if (*s == '\x01' || *s == '\x02' ) |
143 | + //Skip Ctrl-A and Ctrl-B chars e2fsck uses to bracket the progress bar |
144 | + continue; |
145 | + else { |
146 | + if ( cursor < lineend ) { |
147 | + buff .replace( cursor, 1, 1, *s ) ; |
148 | + cursor ++ ; |
149 | + } |
150 | + else { |
151 | + buff .append( 1, *s ) ; |
152 | + cursor ++ ; |
153 | + lineend = cursor ; |
154 | + } |
155 | + } |
156 | + } |
157 | + signal_update.emit(); |
158 | + return true; |
159 | + } |
160 | + if (status != Glib::IO_STATUS_EOF) |
161 | + std::cerr << "Pipe IOChannel read failed" << std::endl; |
162 | + // signal completion |
163 | + signal_eof.emit(); |
164 | + return false; |
165 | +} |
166 | + |
167 | +PipeCapture::~PipeCapture() |
168 | +{ |
169 | + if( sourceid > 0 ) |
170 | + g_source_remove( sourceid ); |
171 | +} |
172 | + |
173 | +} // namespace GParted |
174 | |
175 | === modified file '.pc/applied-patches' |
176 | --- .pc/applied-patches 2014-02-25 14:38:33 +0000 |
177 | +++ .pc/applied-patches 2014-10-31 14:25:19 +0000 |
178 | @@ -1,2 +1,3 @@ |
179 | 01_fix-desktop.patch |
180 | 02_use-pkexec.patch |
181 | +0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch |
182 | |
183 | === modified file 'debian/changelog' |
184 | --- debian/changelog 2014-07-21 21:20:18 +0000 |
185 | +++ debian/changelog 2014-10-31 14:25:19 +0000 |
186 | @@ -1,3 +1,11 @@ |
187 | +gparted (0.19.0-1ubuntu1) utopic; urgency=medium |
188 | + |
189 | + * 0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch: |
190 | + cherry pick upstream commit fixing a memory corruption error that |
191 | + causes various crashes (LP: #1376051). |
192 | + |
193 | + -- Phillip Susi <psusi@ubuntu.com> Fri, 24 Oct 2014 15:05:27 -0400 |
194 | + |
195 | gparted (0.19.0-1build1) utopic; urgency=medium |
196 | |
197 | * Rebuild against libparted2. |
198 | |
199 | === added file 'debian/patches/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch' |
200 | --- debian/patches/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch 1970-01-01 00:00:00 +0000 |
201 | +++ debian/patches/0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch 2014-10-31 14:25:19 +0000 |
202 | @@ -0,0 +1,215 @@ |
203 | +From 0fcfd18061a45f208415971f190818a41cc59f47 Mon Sep 17 00:00:00 2001 |
204 | +From: Mike Fleetwood <mike.fleetwood@googlemail.com> |
205 | +Date: Sat, 5 Jul 2014 09:35:45 +0100 |
206 | +Subject: [PATCH] Prevent cross thread write after free in _OnReadable() |
207 | + (#731752) |
208 | + |
209 | +Fragment of debugging and valgrind output: |
210 | +D: tid=2193 main() |
211 | +... |
212 | +D: tid=2202 GParted_Core::set_devices_thread() |
213 | +... |
214 | +D: tid=2202 Utils::execute_command(command="dumpe2fs -h /dev/sda1", output, error, use_C_locale=1) |
215 | +D: tid=2202 this=0x13fef4a0 PipeCapture::PipeCapture() |
216 | +D: tid=2202 this=0x13fef4f0 PipeCapture::PipeCapture() |
217 | +D: tid=2202 this=0x13fef4a0 PipeCapture::connect_signal() |
218 | +D: sourceid=77 |
219 | +D: tid=2202 this=0x13fef4f0 PipeCapture::connect_signal() |
220 | +D: sourceid=78 |
221 | +D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable() |
222 | +D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable() |
223 | +D: signal_update.emit() |
224 | +D: return true |
225 | +D: tid=2193 data=0x13fef4f0 PipeCapture::_OnReadable() |
226 | +D: tid=2193 this=0x13fef4f0 PipeCapture::OnReadable() |
227 | +D: signal_update.emit() |
228 | +D: return true |
229 | +D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable() |
230 | +D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable() |
231 | +D: signal_update.emit() |
232 | +D: return true |
233 | +D: tid=2193 data=0x13fef4f0 PipeCapture::_OnReadable() |
234 | +D: tid=2193 this=0x13fef4f0 PipeCapture::OnReadable() |
235 | +D: signal_eof.emit() |
236 | +D: return false |
237 | +D: (!rc) &(pc->sourceid)=0x13fef518 |
238 | +D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable() |
239 | +D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable() |
240 | +D: signal_update.emit() |
241 | +D: return true |
242 | +D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable() |
243 | +D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable() |
244 | +D: signal_update.emit() |
245 | +D: return true |
246 | +D: tid=2193 data=0x13fef4a0 PipeCapture::_OnReadable() |
247 | +D: tid=2193 this=0x13fef4a0 PipeCapture::OnReadable() |
248 | +D: signal_eof.emit() |
249 | +D: tid=2202 this=0x13fef4f0 PipeCapture::~PipeCapture() |
250 | +D: sourceid=0 |
251 | +D: tid=2202 this=0x13fef4a0 PipeCapture::~PipeCapture() |
252 | +D: sourceid=77 |
253 | +D: return false |
254 | +D: (!rc) &(pc->sourceid)=0x13fef4c8 |
255 | +==2193== Thread 1: |
256 | +==2193== Invalid write of size 4 |
257 | +==2193== at 0x490580: GParted::PipeCapture::_OnReadable(_GIOChannel*, GIOCondition, void*) (PipeCapture.cc:56) |
258 | +==2193== by 0x38662492A5: g_main_context_dispatch (gmain.c:3066) |
259 | +==2193== by 0x3866249627: g_main_context_iterate.isra.24 (gmain.c:3713) |
260 | +==2193== by 0x3866249A39: g_main_loop_run (gmain.c:3907) |
261 | +==2193== by 0x3D7FD45C26: gtk_main (gtkmain.c:1257) |
262 | +==2193== by 0x469743: GParted::GParted_Core::set_devices(std::vector<GParted::Device, std::allocator<GParted::Device> >&) (GParted_Core.cc:155) |
263 | +==2193== by 0x4A78F1: GParted::Win_GParted::menu_gparted_refresh_devices() (Win_GParted.cc:1259) |
264 | +==2193== by 0x4A7886: GParted::Win_GParted::on_show() (Win_GParted.cc:1253) |
265 | +==2193== by 0x3D82B2009C: Gtk::Widget_Class::show_callback(_GtkWidget*) (widget.cc:3855) |
266 | +==2193== by 0x3867210297: g_closure_invoke (gclosure.c:777) |
267 | +==2193== by 0x3867221B86: signal_emit_unlocked_R (gsignal.c:3516) |
268 | +==2193== by 0x386722A0F1: g_signal_emit_valist (gsignal.c:3330) |
269 | +==2193== Address 0x13fef4c8 is not stack'd, malloc'd or (recently) free'd |
270 | +==2193== |
271 | + |
272 | +PipeCapture.cc (with debugging): |
273 | + 46 gboolean PipeCapture::_OnReadable( GIOChannel *source, |
274 | + 47 GIOCondition condition, |
275 | + 48 gpointer data ) |
276 | + 49 { |
277 | + 50 std::cout << "D: tid=" << (long int)syscall(SYS_gettid) << " data=" << data << " PipeCapture::_OnReadable()" << std::endl; |
278 | + 51 PipeCapture *pc = static_cast<PipeCapture *>(data); |
279 | + 52 gboolean rc = pc->OnReadable( Glib::IOCondition(condition) ); |
280 | + 53 if (!rc) |
281 | + 54 { |
282 | + 55 std::cout << "D: (!rc) &(pc->sourceid)=" << &(pc->sourceid) << std::endl; |
283 | + 56 pc->sourceid = 0; |
284 | + 57 } |
285 | + 58 return rc; |
286 | + 59 } |
287 | + |
288 | +The use after free across threads only happens when an external program |
289 | +is being executed from a thread other than the main() thread. This is |
290 | +because by default glib registered callbacks are run by the glib main |
291 | +loop, which is only called from the main() thread with Gtk::Main::run(). |
292 | + |
293 | +Event sequence: |
294 | +tid=2193 tid=2202 |
295 | + |
296 | +main() |
297 | +... |
298 | + GParted_Core::set_devices() |
299 | + Glib::Thread::create(... set_devices_thread ...) |
300 | + Gtk::Main::run() GParted_Core::set_devices_thread() |
301 | + ... |
302 | + Utils::execute_command("dumpe2fs ... /dev/sda1" ...) |
303 | + Glib::spawn_async_with_pipes() |
304 | + PipeCapture outputcapture(out, output) |
305 | + outputcapture.connect_signal() |
306 | + //Glib main loop runs callback |
307 | + PipeCapture::_OnReadable() |
308 | + pc->OnReadable() |
309 | + //output read |
310 | + signal_update.emit() |
311 | + return true |
312 | + ... |
313 | + //Glib main loop runs callback |
314 | + PipeCapture::_OnReadable() |
315 | + pc->OnReadable() |
316 | + //eof reached |
317 | +[1] signal_eof.emit() |
318 | + return status.exit_status |
319 | +[2] PipeCapture::~PipeCapture() |
320 | +[3] return false |
321 | +[4] pc->sourceid = 0 |
322 | + |
323 | +What is happening is that the PipeCapture destructor [2] is running in |
324 | +the set_devices_thread() thread and freeing the object's memory as soon |
325 | +as signal_eof.emit() [1] has been called. Then signal_eof.emit() |
326 | +returns back to OnReadable() which then returns false [3] back to the |
327 | +_OnReadable() callback function which then assigns 0 to sourceid member |
328 | +variable [4] in the already freed object, detected by valgrind as: |
329 | + Invalid write of size 4 |
330 | + at ... GParted::PipeCapture::_OnReadable(...) (PipeCapture.cc:56) |
331 | + |
332 | +This is happening because PipeCapture member variable sourceid is being |
333 | +saved, in a different thread, just so the _OnReadable() callback can be |
334 | +removed. However a glib IOChannel callback, type GIOFunc(), returning |
335 | +false will be automatically removed. |
336 | + |
337 | + GLib Reference Manual 2.26 / IO Channels |
338 | + https://developer.gnome.org/glib/2.26/glib-IO-Channels.html#GIOFunc |
339 | + |
340 | + GIOFunc() |
341 | + |
342 | + Returns : the function should return FALSE if the event source |
343 | + should be removed |
344 | + |
345 | +Therefore fix by just not saving the event sourceid at all, and not |
346 | +calling g_source_remove() to manually remove the callback, but instead |
347 | +letting glib automatically remove the callback when it returns false. |
348 | + |
349 | +Bug #731752 - Write after free cross thread race in |
350 | + PipeCapture::_OnReadable() |
351 | +--- |
352 | + include/PipeCapture.h | 1 - |
353 | + src/PipeCapture.cc | 15 +++++---------- |
354 | + 2 files changed, 5 insertions(+), 11 deletions(-) |
355 | + |
356 | +diff --git a/include/PipeCapture.h b/include/PipeCapture.h |
357 | +index e37eba8..d3e2152 100644 |
358 | +--- a/include/PipeCapture.h |
359 | ++++ b/include/PipeCapture.h |
360 | +@@ -31,7 +31,6 @@ class PipeCapture |
361 | + Glib::ustring::size_type cursor ; |
362 | + Glib::ustring::size_type lineend ; |
363 | + Glib::RefPtr<Glib::IOChannel> channel; |
364 | +- guint sourceid; |
365 | + bool OnReadable( Glib::IOCondition condition ); |
366 | + static gboolean _OnReadable( GIOChannel *source, |
367 | + GIOCondition condition, |
368 | +diff --git a/src/PipeCapture.cc b/src/PipeCapture.cc |
369 | +index bbb400e..2b5d5f8 100644 |
370 | +--- a/src/PipeCapture.cc |
371 | ++++ b/src/PipeCapture.cc |
372 | +@@ -20,8 +20,7 @@ |
373 | + namespace GParted { |
374 | + |
375 | + PipeCapture::PipeCapture( int fd, Glib::ustring &string ) : buff( string ), |
376 | +- linestart( 0 ), cursor( 0 ), lineend( 0 ), |
377 | +- sourceid( 0 ) |
378 | ++ linestart( 0 ), cursor( 0 ), lineend( 0 ) |
379 | + { |
380 | + // tie fd to string |
381 | + // make channel |
382 | +@@ -31,10 +30,10 @@ PipeCapture::PipeCapture( int fd, Glib::ustring &string ) : buff( string ), |
383 | + void PipeCapture::connect_signal() |
384 | + { |
385 | + // connect handler to signal input/output |
386 | +- sourceid = g_io_add_watch( channel->gobj(), |
387 | +- GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP), |
388 | +- _OnReadable, |
389 | +- this ); |
390 | ++ g_io_add_watch( channel->gobj(), |
391 | ++ GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP), |
392 | ++ _OnReadable, |
393 | ++ this ); |
394 | + } |
395 | + |
396 | + gboolean PipeCapture::_OnReadable( GIOChannel *source, |
397 | +@@ -43,8 +42,6 @@ gboolean PipeCapture::_OnReadable( GIOChannel *source, |
398 | + { |
399 | + PipeCapture *pc = static_cast<PipeCapture *>(data); |
400 | + gboolean rc = pc->OnReadable( Glib::IOCondition(condition) ); |
401 | +- if (!rc) |
402 | +- pc->sourceid = 0; |
403 | + return rc; |
404 | + } |
405 | + |
406 | +@@ -104,8 +101,6 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition ) |
407 | + |
408 | + PipeCapture::~PipeCapture() |
409 | + { |
410 | +- if( sourceid > 0 ) |
411 | +- g_source_remove( sourceid ); |
412 | + } |
413 | + |
414 | + } // namespace GParted |
415 | +-- |
416 | +1.9.1 |
417 | + |
418 | |
419 | === modified file 'debian/patches/series' |
420 | --- debian/patches/series 2014-02-25 14:38:33 +0000 |
421 | +++ debian/patches/series 2014-10-31 14:25:19 +0000 |
422 | @@ -1,3 +1,4 @@ |
423 | 01_fix-desktop.patch |
424 | 02_use-pkexec.patch |
425 | |
426 | +0001-Prevent-cross-thread-write-after-free-in-_OnReadable.patch |
427 | |
428 | === modified file 'include/PipeCapture.h' |
429 | --- include/PipeCapture.h 2014-02-25 14:38:33 +0000 |
430 | +++ include/PipeCapture.h 2014-10-31 14:25:19 +0000 |
431 | @@ -31,7 +31,6 @@ |
432 | Glib::ustring::size_type cursor ; |
433 | Glib::ustring::size_type lineend ; |
434 | Glib::RefPtr<Glib::IOChannel> channel; |
435 | - guint sourceid; |
436 | bool OnReadable( Glib::IOCondition condition ); |
437 | static gboolean _OnReadable( GIOChannel *source, |
438 | GIOCondition condition, |
439 | |
440 | === modified file 'src/PipeCapture.cc' |
441 | --- src/PipeCapture.cc 2014-06-11 10:50:11 +0000 |
442 | +++ src/PipeCapture.cc 2014-10-31 14:25:19 +0000 |
443 | @@ -20,8 +20,7 @@ |
444 | namespace GParted { |
445 | |
446 | PipeCapture::PipeCapture( int fd, Glib::ustring &string ) : buff( string ), |
447 | - linestart( 0 ), cursor( 0 ), lineend( 0 ), |
448 | - sourceid( 0 ) |
449 | + linestart( 0 ), cursor( 0 ), lineend( 0 ) |
450 | { |
451 | // tie fd to string |
452 | // make channel |
453 | @@ -31,10 +30,10 @@ |
454 | void PipeCapture::connect_signal() |
455 | { |
456 | // connect handler to signal input/output |
457 | - sourceid = g_io_add_watch( channel->gobj(), |
458 | - GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP), |
459 | - _OnReadable, |
460 | - this ); |
461 | + g_io_add_watch( channel->gobj(), |
462 | + GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP), |
463 | + _OnReadable, |
464 | + this ); |
465 | } |
466 | |
467 | gboolean PipeCapture::_OnReadable( GIOChannel *source, |
468 | @@ -43,8 +42,6 @@ |
469 | { |
470 | PipeCapture *pc = static_cast<PipeCapture *>(data); |
471 | gboolean rc = pc->OnReadable( Glib::IOCondition(condition) ); |
472 | - if (!rc) |
473 | - pc->sourceid = 0; |
474 | return rc; |
475 | } |
476 | |
477 | @@ -104,8 +101,6 @@ |
478 | |
479 | PipeCapture::~PipeCapture() |
480 | { |
481 | - if( sourceid > 0 ) |
482 | - g_source_remove( sourceid ); |
483 | } |
484 | |
485 | } // namespace GParted |
I've uploaded this to the utopic proposed queue. Thanks for working on this.