def testMassCloseFileDescriptors(self): # Open /dev/null s = open("/dev/null") # Start with fd 500 start = 500 # Open file descriptors, spaced apart def openFDs(): os.dup2(s.fileno(), start + 0) os.dup2(s.fileno(), start + 2) os.dup2(s.fileno(), start + 5) os.dup2(s.fileno(), start + 9) os.dup2(s.fileno(), start + 13) os.dup2(s.fileno(), start + 17) os.dup2(s.fileno(), start + 27) openFDs() util.massCloseFileDescriptors(start, 4) # 17 should be closed self.assertRaises(OSError, os.read, start + 17, 1) # 27 should still be open os.read(start + 27, 1) os.close(start + 27) openFDs() util.massCloseFileDescriptors(start, 10) # 27 should be closed now self.assertRaises(OSError, os.read, start + 27, 1) # Test for low-level misc function openFDs() file_utils.massCloseFileDescriptors(start, 0, start + 20) # 27 should still be open os.read(start + 27, 1) file_utils.massCloseFileDescriptors(start, 0, start + 30) # 27 should be closed now self.assertRaises(OSError, os.read, start + 27, 1)
def loadEntitlementFromProgram(fullPath, serverName): """ Executes the given file to generate an entitlement. The executable must print to stdout a full valid entitlement xml blob. """ readFd, writeFd = os.pipe() stdErrRead, stdErrWrite = os.pipe() childPid = os.fork() if not childPid: nullFd = os.open("/dev/null", os.O_RDONLY) try: try: os.close(readFd) # switch stdin to /dev/null os.dup2(nullFd, 0) os.close(nullFd) # both error and stderr are redirected - the entitlement # should be on stdout, and error info should be # on stderr. os.dup2(writeFd, 1) os.dup2(stdErrWrite, 2) os.close(writeFd) os.close(stdErrWrite) util.massCloseFileDescriptors(3, 252) os.execl(fullPath, fullPath, serverName) except Exception: traceback.print_exc(sys.stderr) finally: os._exit(1) os.close(writeFd) os.close(stdErrWrite) # read in from pipes. When they're closed, # the child process should have exited. output = [] errorOutput = [] buf = os.read(readFd, 1024) errBuf = os.read(stdErrRead, 1024) while buf or errBuf: if buf: output.append(buf) buf = os.read(readFd, 1024) if errBuf: errorOutput.append(errBuf) errBuf = os.read(stdErrRead, 1024) pid, status = os.waitpid(childPid, 0) os.close(readFd) os.close(stdErrRead) errMsg = '' if os.WIFEXITED(status) and os.WEXITSTATUS(status): errMsg = ('Entitlement generator at "%s"' ' died with exit status %d' % (fullPath, os.WEXITSTATUS(status))) elif os.WIFSIGNALED(status): errMsg = ('Entitlement generator at "%s"' ' died with signal %d' % (fullPath, os.WTERMSIG(status))) else: errMsg = '' if errMsg: if errorOutput: errMsg += ' - stderr output follows:\n%s' % ''.join(errorOutput) else: errMsg += ' - no output on stderr' raise errors.ConaryError(errMsg) # looks like we generated an entitlement - they're still the possibility # that the entitlement is broken. xmlContent = ''.join(output) return loadEntitlementFromString(xmlContent, fullPath)