At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3767
revision-id: [EMAIL PROTECTED]
parent: [EMAIL PROTECTED]
parent: [EMAIL PROTECTED]
committer: Canonical.com Patch Queue Manager <[EMAIL PROTECTED]>
branch nick: +trunk
timestamp: Tue 2008-10-07 07:38:15 +0100
message:
  (mbp) #279381 reset errno before calling readdir
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.1.6
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 17:02:24 +1100
    message:
      We need a 'global' declaration to assign to errno; and fix comments
    modified:
      bzrlib/_readdir_pyx.pyx        
readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.1.5
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 16:18:52 +1100
    message:
      add missing pyrex import
    modified:
      bzrlib/_readdir_pyx.pyx        
readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.1.4
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 15:41:23 +1100
    message:
      update news
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3766.1.3
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 15:39:43 +1100
    message:
      doc
    modified:
      bzrlib/_readdir_pyx.pyx        
readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.1.2
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 14:28:39 +1100
    message:
      Be a bit more careful about checking readdir result
    modified:
      bzrlib/_readdir_pyx.pyx        
readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.1.1
    revision-id: [EMAIL PROTECTED]
    parent: [EMAIL PROTECTED]
    committer: Martin Pool <[EMAIL PROTECTED]>
    branch nick: 279381-readdir
    timestamp: Tue 2008-10-07 14:19:42 +1100
    message:
      Fix errors in calling readdir from pyrex (lp:279381)
      
      readdir is unusual because it returns NULL for both eof and error, and 
does not
      clear errno in the first case.
      
      Also, if EINTR or EAGAIN is raised from readdir, we need to continue 
reading, 
      not assume that's the end of the directory!
    modified:
      bzrlib/_readdir_pyx.pyx        
readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
=== modified file 'NEWS'
--- a/NEWS      2008-10-03 00:18:15 +0000
+++ b/NEWS      2008-10-07 04:41:23 +0000
@@ -79,6 +79,10 @@
 
   BUG FIXES:
 
+    * Avoid random failures arising from misinterpreted ``errno`` values
+      in ``_readdir_pyx.read_dir``.
+      (Martin Pool, #279381)
+
     * Branching from a shared repository on a smart server into a new
       repository now preserves the repository format.
       (Andrew Bennetts, #269214)

=== modified file 'bzrlib/_readdir_pyx.pyx'
--- a/bzrlib/_readdir_pyx.pyx   2008-09-24 04:15:03 +0000
+++ b/bzrlib/_readdir_pyx.pyx   2008-10-07 06:02:24 +0000
@@ -25,13 +25,14 @@
     pass
 
 
-# the opaque C library DIR type.
 cdef extern from 'errno.h':
     int ENOENT
     int ENOTDIR
     int EAGAIN
+    int EINTR
+    char *strerror(int errno)
+    # not necessarily a real variable, but this should be close enough
     int errno
-    char *strerror(int errno)
 
 cdef extern from 'unistd.h':
     int chdir(char *path)
@@ -89,6 +90,7 @@
     ctypedef struct dirent:
         char d_name[256]
         ino_t d_ino
+    # the opaque C library DIR type.
     ctypedef struct DIR
     # should be DIR *, pyrex barfs.
     DIR * opendir(char * name)
@@ -278,6 +280,7 @@
     cdef int stat_result
     cdef _Stat statvalue
     cdef char *cwd
+    global errno
 
     cwd = getcwd(NULL, 0)
     if -1 == chdir(path):
@@ -289,21 +292,30 @@
     try:
         entry = &sentinel
         while entry != NULL:
-            entry = readdir(the_dir)
+            # Unlike most libc functions, readdir needs errno set to 0
+            # beforehand so that eof can be distinguished from errors.  See
+            # <https://bugs.launchpad.net/bzr/+bug/279381>
+            while True:
+                errno = 0;
+                entry = readdir(the_dir)
+                if entry == NULL and (errno == EAGAIN or errno == EINTR):
+                    # try again
+                    continue
+                else:
+                    break
             if entry == NULL:
-                if errno == EAGAIN:
-                    # try again
-                    continue
-                elif errno != ENOTDIR and errno != ENOENT and errno != 0:
+                if errno == ENOTDIR or errno == ENOENT or errno == 0:
                     # We see ENOTDIR at the end of a normal directory.
                     # As ENOTDIR for read_dir(file) is triggered on opendir,
                     # we consider ENOTDIR to be 'no error'.
-                    # ENOENT is listed as 'invalid position in the dir stream' 
for
-                    # readdir. We swallow this for now and just keep reading.
+                    #
+                    # XXX: ENOENT is listed as 'invalid position in the dir 
stream' for
+                    # readdir.  It's not clear what we should do about that
+                    # case; at the moment we treat it as the end of the
+                    # directory.
+                    continue
+                else:
                     raise OSError(errno, strerror(errno))
-                else:
-                    # done
-                    continue
             name = entry.d_name
             if not (name[0] == c"." and (
                 (name[1] == 0) or 


-- 
bazaar-commits mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/bazaar-commits

Reply via email to