[Sugar-devel] [PATCH] sl#3286: race condition fixed by making the read- and write- calls pseudo synchronous.

Ajay Garg ajay at activitycentral.com
Fri Jan 20 16:10:31 EST 2012


---

The workflow to read and write data has been made
pseudo-synchronous.

The "write_async" call is executed, after the execution
of "read_async" call; and the "next" "read_async" call
is executed, after the "current" "write_async" call has
been completed.

Note that, the testing was done with the 860-bytes "__init__.py"
file (http://bugs.sugarlabs.org/ticket/3286#comment:3)

Without this patch, the buggy condition occurred about 7/10 times; with
the patch applied, it occurred 0/30 times.


 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/src/jarabe/model/filetransfer.py
+++ b/src/jarabe/model/filetransfer.py
@@ -70,46 +70,43 @@ class StreamSplicer(gobject.GObject):
 
         self._input_stream = input_stream
         self._output_stream = output_stream
-        self._pending_buffers = []
 
     def start(self):
         self._input_stream.read_async(self._CHUNK_SIZE, self.__read_async_cb,
                                       gobject.PRIORITY_LOW)
 
+    """
+    Fix for bug sl#3286.
+
+    The workflow to read and write data has been made
+    pseudo-synchronous.
+    The "write_async" call is executed, after the execution
+    of "read_async" call; and the "next" "read_async" call
+    is executed, after the "current" "write_async" call has
+    been completed.
+    """
     def __read_async_cb(self, input_stream, result):
         data = input_stream.read_finish(result)
 
         if not data:
             logging.debug('closing input stream')
             self._input_stream.close()
-        else:
-            self._pending_buffers.append(data)
-            self._input_stream.read_async(self._CHUNK_SIZE,
-                                            self.__read_async_cb,
-                                            gobject.PRIORITY_LOW)
-        self._write_next_buffer()
-
-    def __write_async_cb(self, output_stream, result, user_data):
-        count_ = output_stream.write_finish(result)
-
-        if not self._pending_buffers and \
-                not self._output_stream.has_pending() and \
-                not self._input_stream.has_pending():
             logging.debug('closing output stream')
-            output_stream.close()
+            self._output_stream.close()
             self.emit('finished')
         else:
-            self._write_next_buffer()
-
-    def _write_next_buffer(self):
-        if self._pending_buffers and not self._output_stream.has_pending():
-            data = self._pending_buffers.pop(0)
             # TODO: we pass the buffer as user_data because of
             # http://bugzilla.gnome.org/show_bug.cgi?id=564102
             self._output_stream.write_async(data, self.__write_async_cb,
                                             gobject.PRIORITY_LOW,
                                             user_data=data)
 
+    def __write_async_cb(self, output_stream, result, user_data):
+        output_stream.write_finish(result)
+        self._input_stream.read_async(self._CHUNK_SIZE,
+                                      self.__read_async_cb,
+                                      gobject.PRIORITY_LOW)
+
 
 class BaseFileTransfer(gobject.GObject):
 
-- 
1.7.4.4



More information about the Sugar-devel mailing list