D2404: util: enable observing of os.read() from bufferedinputpipe

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Fri Feb 23 14:01:46 EST 2018


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Our file object proxy is useful. But it doesn't capture all I/O.
  The "os" module offers low-level interfaces to various system calls.
  For example, os.read() exposes read(2) to read from a file
  descriptor.
  
  This commit teaches the bufferedinputpipe to be aware of when
  a file object is a fileobjectproxy and to signal into its
  observer when an os.read() operation is performed.
  
  If we end up doing this for multiple os.* functions, we may want
  a more generic way to do this wrapping and signaling. But until
  then, a one-off seems appropriate.
  
  This change will allow us to observe I/O on non-raw sshpeer
  instances, since they convert stdout into a bufferedinputpipe.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2404

AFFECTED FILES
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -451,6 +451,13 @@
             self._lenbuf += len(data)
             self._buffer.append(data)
 
+        # If this is our special proxied file object class, log this I/O,
+        # since os.read() bypasses the proxy.
+        if isinstance(self._input, fileobjectproxy):
+            fn = getattr(self._input._observer, r'osread', None)
+            if fn:
+                self._input._observer.osread(data, _chunksize)
+
 def mmapread(fp):
     try:
         fd = getattr(fp, 'fileno', lambda: fp)()
@@ -503,6 +510,8 @@
 
     def __getattribute__(self, name):
         ours = {
+            r'_observer',
+
             # IOBase
             r'close',
             # closed if a property
@@ -679,6 +688,10 @@
         self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
         self._writedata(res)
 
+    def osread(self, res, size):
+        self.fh.write('%s> osread(%d) -> %d' % (self.name, size, len(res)))
+        self._writedata(res)
+
     def write(self, res, data):
         self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
         self._writedata(data)



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list