From fb4ec2586d34d936613abf015de34e5913d2a294 Mon Sep 17 00:00:00 2001
From: Ajay Garg <ajay@activitycentral.com>
Date: Sat, 28 Jan 2012 14:08:56 +0530
Subject: [PATCH sugar v2] sl#3286: race condition fixed by making the read- and
write- calls pseudo synchronous.
Organization: Sugar Labs Foundation
Signed-off-by: Ajay Garg <ajay@activitycentral.com>
---
Note that this patch is to be applied in full, and not over version-1 patch.
Changes of version-2 over version-1 :
-------------------------------------
a. Corrected the patch description (courtesy Sascha).
src/jarabe/model/filetransfer.py | 37 +++++++++++++++++--------------------
1 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/jarabe/model/filetransfer.py b/src/jarabe/model/filetransfer.py
index 710c3a4..447a74a 100644
a
|
b
|
class StreamSplicer(gobject.GObject): |
70 | 70 | |
71 | 71 | self._input_stream = input_stream |
72 | 72 | self._output_stream = output_stream |
73 | | self._pending_buffers = [] |
74 | 73 | |
75 | 74 | def start(self): |
76 | 75 | self._input_stream.read_async(self._CHUNK_SIZE, self.__read_async_cb, |
77 | 76 | gobject.PRIORITY_LOW) |
78 | 77 | |
| 78 | """ |
| 79 | Fix for bug sl#3286. |
| 80 | |
| 81 | The workflow to read and write data has been made |
| 82 | pseudo-synchronous. |
| 83 | The "write_async" call is executed, after the execution |
| 84 | of "read_async" call; and the "next" "read_async" call |
| 85 | is executed, after the "current" "write_async" call has |
| 86 | been completed. |
| 87 | """ |
79 | 88 | def __read_async_cb(self, input_stream, result): |
80 | 89 | data = input_stream.read_finish(result) |
81 | 90 | |
82 | 91 | if not data: |
83 | 92 | logging.debug('closing input stream') |
84 | 93 | self._input_stream.close() |
85 | | else: |
86 | | self._pending_buffers.append(data) |
87 | | self._input_stream.read_async(self._CHUNK_SIZE, |
88 | | self.__read_async_cb, |
89 | | gobject.PRIORITY_LOW) |
90 | | self._write_next_buffer() |
91 | | |
92 | | def __write_async_cb(self, output_stream, result, user_data): |
93 | | count_ = output_stream.write_finish(result) |
94 | | |
95 | | if not self._pending_buffers and \ |
96 | | not self._output_stream.has_pending() and \ |
97 | | not self._input_stream.has_pending(): |
98 | 94 | logging.debug('closing output stream') |
99 | | output_stream.close() |
| 95 | self._output_stream.close() |
100 | 96 | self.emit('finished') |
101 | 97 | else: |
102 | | self._write_next_buffer() |
103 | | |
104 | | def _write_next_buffer(self): |
105 | | if self._pending_buffers and not self._output_stream.has_pending(): |
106 | | data = self._pending_buffers.pop(0) |
107 | 98 | # TODO: we pass the buffer as user_data because of |
108 | 99 | # http://bugzilla.gnome.org/show_bug.cgi?id=564102 |
109 | 100 | self._output_stream.write_async(data, self.__write_async_cb, |
110 | 101 | gobject.PRIORITY_LOW, |
111 | 102 | user_data=data) |
112 | 103 | |
| 104 | def __write_async_cb(self, output_stream, result, user_data): |
| 105 | output_stream.write_finish(result) |
| 106 | self._input_stream.read_async(self._CHUNK_SIZE, |
| 107 | self.__read_async_cb, |
| 108 | gobject.PRIORITY_LOW) |
| 109 | |
113 | 110 | |
114 | 111 | class BaseFileTransfer(gobject.GObject): |
115 | 112 | |