1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17  import os 
 18  from twisted.internet import process 
 19  from twisted.python import log 
 20   
 22      log.msg("Applying patch for http://twistedmatrix.com/trac/ticket/4881") 
 23      process._listOpenFDs = _listOpenFDs 
  24   
 25   
 26   
 27   
 28   
 29   
 30   
 31   
 32   
 33   
 34   
 35   
 36   
 37   
 38   
 39   
 40   
 41   
 42   
 43   
 44   
 45   
 46   
 47   
 48   
 49   
 50   
 51   
 52   
 53   
 54   
 55   
 56   
 57   
 58   
 59   
 60   
 61   
 62   
 63   
 64   
 65   
 66   
 67   
 68   
 69   
 70   
 71   
 72   
 73   
 74   
 75   
 76   
 77   
 78   
 79   
 80   
 81   
 82   
 83   
 84   
 85   
 86   
 87   
 88   
 89   
 90   
 91   
 92   
 93   
 94   
 95   
 97      """ 
 98      This class contains the logic necessary to decide which of the available 
 99      system techniques should be used to detect the open file descriptors for 
100      the current process. The chosen technique gets monkey-patched into the 
101      _listOpenFDs method of this class so that the detection only needs to occur 
102      once. 
103   
104      @ivars listdir: The implementation of listdir to use. This gets overwritten 
105          by the test cases. 
106      @ivars getpid: The implementation of getpid to use, returns the PID of the 
107          running process. 
108      @ivars openfile: The implementation of open() to use, by default the Python 
109          builtin. 
110      """ 
111       
112      listdir = os.listdir 
113      getpid = os.getpid 
114      openfile = open 
115   
116   
118          """ 
119          Figure out which implementation to use, then run it. 
120          """ 
121          self._listOpenFDs = self._getImplementation() 
122          return self._listOpenFDs() 
 123   
124   
126          """ 
127          Check if /dev/fd works, if so, use that.  Otherwise, check if 
128          /proc/%d/fd exists, if so use that. 
129           
130          Otherwise, ask resource.getrlimit, if that throws an exception, then 
131          fallback to _fallbackFDImplementation. 
132          """ 
133          try: 
134              self.listdir("/dev/fd") 
135              if self._checkDevFDSanity():  
136                  return self._devFDImplementation 
137              else: 
138                  return self._fallbackFDImplementation 
139          except: 
140              try: 
141                  self.listdir("/proc/%d/fd" % (self.getpid(),)) 
142                  return self._procFDImplementation 
143              except: 
144                  try: 
145                      self._resourceFDImplementation()  
146                      return self._resourceFDImplementation 
147                  except: 
148                      return self._fallbackFDImplementation 
 149   
150   
152          """ 
153          Returns true iff opening a file modifies the fds visible 
154          in /dev/fd, as it should on a sane platform. 
155          """ 
156          start = self.listdir("/dev/fd") 
157          self.openfile("/dev/null", "r")  
158          end = self.listdir("/dev/fd") 
159          return start != end 
 160   
161   
163          """ 
164          Simple implementation for systems where /dev/fd actually works. 
165          See: http://www.freebsd.org/cgi/man.cgi?fdescfs 
166          """ 
167          dname = "/dev/fd" 
168          result = [int(fd) for fd in os.listdir(dname)] 
169          return result 
 170   
171   
173          """ 
174          Simple implementation for systems where /proc/pid/fd exists (we assume 
175          it works). 
176          """ 
177          dname = "/proc/%d/fd" % (os.getpid(),) 
178          return [int(fd) for fd in os.listdir(dname)] 
 179   
180   
182          """ 
183          Fallback implementation where the resource module can inform us about 
184          how many FDs we can expect. 
185   
186          Note that on OS-X we expect to be using the /dev/fd implementation. 
187          """ 
188          import resource 
189          maxfds = resource.getrlimit(resource.RLIMIT_NOFILE)[1] + 1 
190           
191           
192          if maxfds > 1024: 
193              maxfds = 1024 
194          return xrange(maxfds) 
 195   
196   
198          """ 
199          Fallback-fallback implementation where we just assume that we need to 
200          close 256 FDs. 
201          """ 
202          maxfds = 256 
203          return xrange(maxfds) 
  204   
205   
206  detector = _FDDetector() 
207   
209      """ 
210      Use the global detector object to figure out which FD implementation to 
211      use. 
212      """ 
213      return detector._listOpenFDs() 
 214