Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4:Update
python3.370
python-2.6b1-subprocess-eintr-safety.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File python-2.6b1-subprocess-eintr-safety.patch of Package python3.370
--- Lib/subprocess.py 2007-03-14 19:16:36.000000000 +0100 +++ Lib/subprocess.py 2007-03-14 19:18:50.000000000 +0100 @@ -655,14 +655,14 @@ class Popen(object): stderr = None if self.stdin: if input: - self.stdin.write(input) + self._fo_write_no_intr(self.stdin, input) self.stdin.close() elif self.stdout: - stdout = self.stdout.read() + stdout = self._fo_read_no_intr(self.stdout) self.stdout.close() elif self.stderr: - stderr = self.stderr.read() + stderr = self._fo_read_no_intr(self.stderr) self.stderr.close() self.wait() return (stdout, stderr) @@ -977,6 +977,62 @@ class Popen(object): pass + def _read_no_intr(self, fd, buffersize): + """Like os.read, but retries on EINTR""" + while True: + try: + return os.read(fd, buffersize) + except OSError, e: + if e.errno == errno.EINTR: + continue + else: + raise + + + def _write_no_intr(self, fd, s): + """Like os.write, but retries on EINTR""" + while True: + try: + return os.write(fd, s) + except OSError, e: + if e.errno == errno.EINTR: + continue + else: + raise + + def _waitpid_no_intr(self, pid, options): + """Like os.waitpid, but retries on EINTR""" + while True: + try: + return os.waitpid(pid, options) + except OSError, e: + if e.errno == errno.EINTR: + continue + else: + raise + + def _fo_read_no_intr(self, obj): + """Like obj.read(), but retries on EINTR""" + while True: + try: + return obj.read() + except IOError, e: + if e.errno == errno.EINTR: + continue + else: + raise + + def _fo_write_no_intr(self, obj, data): + """Like obj.write(), but retries on EINTR""" + while True: + try: + return obj.write(data) + except IOError, e: + if e.errno == errno.EINTR: + continue + else: + raise + def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, @@ -1055,7 +1121,7 @@ class Popen(object): exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) - os.write(errpipe_write, pickle.dumps(exc_value)) + self._write_no_intr(errpipe_write, pickle.dumps(exc_value)) # This exitcode won't be reported to applications, so it # really doesn't matter what we return. @@ -1071,10 +1137,10 @@ class Popen(object): os.close(errwrite) # Wait for exec to fail or succeed; possibly raising exception - data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB + data = self._read_no_intr(errpipe_read, 1048576) # Exceptions limited to 1 MB os.close(errpipe_read) if data: - os.waitpid(self.pid, 0) + self._waitpid_no_intr(self.pid, 0) child_exception = pickle.loads(data) raise child_exception @@ -1094,7 +1160,7 @@ class Popen(object): attribute.""" if self.returncode is None: try: - pid, sts = os.waitpid(self.pid, os.WNOHANG) + pid, sts = self._waitpid_no_intr(self.pid, os.WNOHANG) if pid == self.pid: self._handle_exitstatus(sts) except os.error: @@ -1107,7 +1173,7 @@ class Popen(object): """Wait for child process to terminate. Returns returncode attribute.""" if self.returncode is None: - pid, sts = os.waitpid(self.pid, 0) + pid, sts = self._waitpid_no_intr(self.pid, 0) self._handle_exitstatus(sts) return self.returncode @@ -1135,27 +1201,33 @@ class Popen(object): input_offset = 0 while read_set or write_set: - rlist, wlist, xlist = select.select(read_set, write_set, []) + try: + rlist, wlist, xlist = select.select(read_set, write_set, []) + except select.error, e: + if e[0] == errno.EINTR: + continue + else: + raise if self.stdin in wlist: # When select has indicated that the file is writable, # we can write up to PIPE_BUF bytes without risk # blocking. POSIX defines PIPE_BUF >= 512 - bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) + bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512)) input_offset += bytes_written if input_offset >= len(input): self.stdin.close() write_set.remove(self.stdin) if self.stdout in rlist: - data = os.read(self.stdout.fileno(), 1024) + data = self._read_no_intr(self.stdout.fileno(), 1024) if data == "": self.stdout.close() read_set.remove(self.stdout) stdout.append(data) if self.stderr in rlist: - data = os.read(self.stderr.fileno(), 1024) + data = self._read_no_intr(self.stderr.fileno(), 1024) if data == "": self.stderr.close() read_set.remove(self.stderr) --- Lib/test/test_subprocess.py 2007-03-14 19:16:36.000000000 +0100 +++ Lib/test/test_subprocess.py 2007-03-14 19:18:57.000000000 +0100 @@ -580,6 +578,34 @@ class ProcessTestCase(unittest.TestCase) os.remove(fname) self.assertEqual(rc, 47) + def test_eintr(self): + # retries on EINTR for an argv + + # send ourselves a signal that causes EINTR + prev_handler = signal.signal(signal.SIGALRM, lambda x,y: 1) + signal.alarm(1) + time.sleep(0.5) + + rc = subprocess.Popen(['sleep', '1']) + self.assertEqual(rc.wait(), 0) + + signal.signal(signal.SIGALRM, prev_handler) + + def test_eintr_out(self): + # retries on EINTR for a shell call and pipelining + + # send ourselves a signal that causes EINTR + prev_handler = signal.signal(signal.SIGALRM, lambda x,y: 1) + signal.alarm(1) + time.sleep(0.5) + + rc = subprocess.Popen("sleep 1; echo hello", + shell=True, stdout=subprocess.PIPE) + out = rc.communicate()[0] + self.assertEqual(rc.returncode, 0) + self.assertEqual(out, "hello\n") + + signal.signal(signal.SIGALRM, prev_handler) # # Windows tests
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor