Author: tack
Date: Mon Feb 4 11:41:05 2008
New Revision: 3022
Log:
Support for non-blocking writes. (Note I still intend to rewrite popen.py,
so the use of mixed approaches [e.g. SocketDispatcher vs. notifier.socket_add]
isn't a big deal right now.)
Modified:
trunk/base/src/notifier/popen.py
Modified: trunk/base/src/notifier/popen.py
==============================================================================
--- trunk/base/src/notifier/popen.py (original)
+++ trunk/base/src/notifier/popen.py Mon Feb 4 11:41:05 2008
@@ -59,6 +59,7 @@
from callback import Signal, Callback
from thread import MainThreadCallback, is_mainthread
from async import InProgress
+from sockets import SocketDispatcher, IO_WRITE
# get logging object
log = logging.getLogger('notifier')
@@ -94,6 +95,8 @@
self.__kill_timer = None
self.child = None
self.in_progress = None
+ self._write_buffer = []
+ self._wmon = None
def _normalize_cmd(self, cmd):
@@ -154,6 +157,12 @@
self.child = popen2.Popen3( cmd, True, 100 )
+ flags = fcntl.fcntl(self.child.tochild.fileno(), fcntl.F_GETFL)
+ fcntl.fcntl( self.child.tochild.fileno(), fcntl.F_SETFL, flags |
os.O_NONBLOCK )
+ self._wmon = SocketDispatcher(self._handle_write)
+ if self._write_buffer:
+ self._wmon.register(self.child.tochild, IO_WRITE)
+
log.info('running %s (pid=%s)' % ( self.binary, self.child.pid ) )
# IO_Handler for stdout
@@ -181,16 +190,36 @@
return self.child.pid
- def write( self, line ):
+ def write(self, data):
"""
- Write a string to the app.
+ Queue data for writing when the child is ready to receive it.
"""
+ self._write_buffer.append(data)
+ if self._wmon and not self._wmon.active():
+ self._wmon.register(self.child.tochild, IO_WRITE)
+
+
+ def _handle_write(self):
try:
- if self.child:
- self.child.tochild.write(line)
- self.child.tochild.flush()
- except (IOError, ValueError):
- pass
+ while self._write_buffer:
+ data = self._write_buffer[0]
+ sent = os.write(self.child.tochild.fileno(), data)
+ # If we got here, no exception was raised, so we can pop the
+ # data from the buffer.
+ self._write_buffer.pop(0)
+ if sent != len(data):
+ # Not all data was sent, so push the remaining bytes back
and
+ # abort the loop.
+ self._write_buffer.insert(0, data[sent:])
+ break
+ except IOError, (errno, msg):
+ if errno == 11:
+ # Resource temporarily unavailable -- trying to write too
+ # much data.
+ return
+
+ if not self._write_buffer:
+ return False
def is_alive( self ):
@@ -342,7 +371,7 @@
"""
Reading data from socket (stdout or stderr)
"""
- def __init__( self, name, fp, signal, raw_signal, logger = None, raw =
False):
+ def __init__( self, name, fp, signal, raw_signal, logger = None):
self.name = name
self.fp = fp
flags = fcntl.fcntl(self.fp.fileno(), fcntl.F_GETFL)
@@ -351,7 +380,6 @@
self.raw_signal = raw_signal
self.logger = None
self.saved = ''
- self.raw = raw
notifier.socket_add( fp, self._handle_input )
if logger:
logger = '%s-%s.log' % ( logger, name )
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog