Commit f23135ea authored by Martín Ferrari's avatar Martín Ferrari

Moved the EINTR wrapper into environ, and replaced the many copies of the same...

Moved the EINTR wrapper into environ, and replaced the many copies of the same code scattered around the code. Also made it catch both IOError and OSerror.
parent 103e5496
...@@ -4,7 +4,7 @@ from syslog import LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG ...@@ -4,7 +4,7 @@ from syslog import LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
__all__ = ["ip_path", "tc_path", "brctl_path", "sysctl_path", "hz"] __all__ = ["ip_path", "tc_path", "brctl_path", "sysctl_path", "hz"]
__all__ += ["tcpdump_path", "netperf_path", "xauth_path", "xdpyinfo_path"] __all__ += ["tcpdump_path", "netperf_path", "xauth_path", "xdpyinfo_path"]
__all__ += ["execute", "backticks"] __all__ += ["execute", "backticks", "eintr_wrapper"]
__all__ += ["find_listen_port"] __all__ += ["find_listen_port"]
__all__ += ["LOG_ERR", "LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG"] __all__ += ["LOG_ERR", "LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG"]
__all__ += ["set_log_level", "logger"] __all__ += ["set_log_level", "logger"]
...@@ -74,6 +74,20 @@ def backticks(cmd): ...@@ -74,6 +74,20 @@ def backticks(cmd):
raise RuntimeError("Error executing `%s': %s" % (" ".join(cmd), err)) raise RuntimeError("Error executing `%s': %s" % (" ".join(cmd), err))
return out return out
def eintr_wrapper(f, *args):
"Wraps some callable with a loop that retries on EINTR."
while True:
try:
return f(*args)
except OSError, e: # pragma: no cover
if e.errno == errno.EINTR:
continue
raise
except IOError, e: # pragma: no cover
if e.errno == errno.EINTR:
continue
raise
def find_listen_port(family = socket.AF_INET, type = socket.SOCK_STREAM, def find_listen_port(family = socket.AF_INET, type = socket.SOCK_STREAM,
proto = 0, addr = "127.0.0.1", min_port = 1, max_port = 65535): proto = 0, addr = "127.0.0.1", min_port = 1, max_port = 65535):
s = socket.socket(family, type, proto) s = socket.socket(family, type, proto)
...@@ -133,15 +147,8 @@ def logger(priority, message): ...@@ -133,15 +147,8 @@ def logger(priority, message):
if priority > _log_level: if priority > _log_level:
return return
while True: eintr_wrapper(_log_stream.write,
try: "[%d] %s\n" % (os.getpid(), message.rstrip()))
_log_stream.write("[%d] %s\n" % (os.getpid(), message.rstrip()))
except OSError, e: # pragma: no cover
if e.errno == errno.EINTR:
continue
else:
raise
break
_log_stream.flush() _log_stream.flush()
def error(message): def error(message):
......
...@@ -60,16 +60,7 @@ class Node(object): ...@@ -60,16 +60,7 @@ class Node(object):
if self._slave: if self._slave:
self._slave.shutdown() self._slave.shutdown()
while True: exitcode = eintr_wrapper(os.waitpid, self._pid, 0)[1]
try:
exitcode = os.waitpid(self._pid, 0)[1]
except OSError, e: # pragma: no cover
if e.errno == errno.EINTR:
continue
else:
raise
break
if exitcode != 0: if exitcode != 0:
error("Node(0x%x) process %d exited with non-zero status: %d" % error("Node(0x%x) process %d exited with non-zero status: %d" %
(id(self), self._pid, exitcode)) (id(self), self._pid, exitcode))
......
...@@ -149,8 +149,8 @@ class Server(object): ...@@ -149,8 +149,8 @@ class Server(object):
def readline(self): def readline(self):
"Read a line from the socket and detect connection break-up." "Read a line from the socket and detect connection break-up."
# FIXME: should use the _eintr_wrapper from subprocess: some # FIXME: should use the eintr_wrapper from environ; why was I using
# reorganization needed first. # readline instead of read?
while True: while True:
try: try:
line = self._rfd.readline() line = self._rfd.readline()
...@@ -552,13 +552,7 @@ class Client(object): ...@@ -552,13 +552,7 @@ class Client(object):
raise RuntimeError("Client already shut down.") raise RuntimeError("Client already shut down.")
text = [] text = []
while True: while True:
try: line = eintr_wrapper(self._rfd.readline).rstrip()
line = self._rfd.readline().rstrip()
except IOError, e:
if e.errno == errno.EINTR:
continue
else:
raise e
if not line: if not line:
raise RuntimeError("Protocol error, empty line received") raise RuntimeError("Protocol error, empty line received")
......
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import errno, fcntl, grp, os, pickle, pwd, signal, select, sys, time, traceback import fcntl, grp, os, pickle, pwd, signal, select, sys, time, traceback
from netns.environ import eintr_wrapper
__all__ = [ 'PIPE', 'STDOUT', 'Popen', 'Subprocess', 'spawn', 'wait', 'poll', __all__ = [ 'PIPE', 'STDOUT', 'Popen', 'Subprocess', 'spawn', 'wait', 'poll',
'get_user', 'system', 'backticks', 'backticks_raise' ] 'get_user', 'system', 'backticks', 'backticks_raise' ]
...@@ -167,7 +168,7 @@ class Popen(Subprocess): ...@@ -167,7 +168,7 @@ class Popen(Subprocess):
# Close pipes, they have been dup()ed to the child # Close pipes, they have been dup()ed to the child
for k, v in fdmap.items(): for k, v in fdmap.items():
if getattr(self, k) != None: if getattr(self, k) != None:
_eintr_wrapper(os.close, v) eintr_wrapper(os.close, v)
def communicate(self, input = None): def communicate(self, input = None):
"""See Popen.communicate.""" """See Popen.communicate."""
...@@ -296,10 +297,10 @@ def spawn(executable, argv = None, cwd = None, env = None, close_fds = False, ...@@ -296,10 +297,10 @@ def spawn(executable, argv = None, cwd = None, env = None, close_fds = False,
if userfd[i] != None and userfd[i] >= 0: if userfd[i] != None and userfd[i] >= 0:
os.dup2(userfd[i], i) os.dup2(userfd[i], i)
if userfd[i] != i and userfd[i] not in userfd[0:i]: if userfd[i] != i and userfd[i] not in userfd[0:i]:
_eintr_wrapper(os.close, userfd[i]) # only in child! eintr_wrapper(os.close, userfd[i]) # only in child!
# Set up special control pipe # Set up special control pipe
_eintr_wrapper(os.close, r) eintr_wrapper(os.close, r)
flags = fcntl.fcntl(w, fcntl.F_GETFD) flags = fcntl.fcntl(w, fcntl.F_GETFD)
fcntl.fcntl(w, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC) fcntl.fcntl(w, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
...@@ -345,29 +346,29 @@ def spawn(executable, argv = None, cwd = None, env = None, close_fds = False, ...@@ -345,29 +346,29 @@ def spawn(executable, argv = None, cwd = None, env = None, close_fds = False,
# subprocess.py # subprocess.py
v.child_traceback = "".join( v.child_traceback = "".join(
traceback.format_exception(t, v, tb)) traceback.format_exception(t, v, tb))
_eintr_wrapper(os.write, w, pickle.dumps(v)) eintr_wrapper(os.write, w, pickle.dumps(v))
_eintr_wrapper(os.close, w) eintr_wrapper(os.close, w)
#traceback.print_exc() #traceback.print_exc()
except: except:
traceback.print_exc() traceback.print_exc()
os._exit(1) os._exit(1)
_eintr_wrapper(os.close, w) eintr_wrapper(os.close, w)
# read EOF for success, or a string as error info # read EOF for success, or a string as error info
s = "" s = ""
while True: while True:
s1 = _eintr_wrapper(os.read, r, 4096) s1 = eintr_wrapper(os.read, r, 4096)
if s1 == "": if s1 == "":
break break
s += s1 s += s1
_eintr_wrapper(os.close, r) eintr_wrapper(os.close, r)
if s == "": if s == "":
return pid return pid
# It was an error # It was an error
_eintr_wrapper(os.waitpid, pid, 0) eintr_wrapper(os.waitpid, pid, 0)
exc = pickle.loads(s) exc = pickle.loads(s)
# XXX: sys.excepthook # XXX: sys.excepthook
#print exc.child_traceback #print exc.child_traceback
...@@ -383,7 +384,7 @@ def poll(pid): ...@@ -383,7 +384,7 @@ def poll(pid):
def wait(pid): def wait(pid):
"""Wait for process to die and return the exit code.""" """Wait for process to die and return the exit code."""
return _eintr_wrapper(os.waitpid, pid, 0)[1] return eintr_wrapper(os.waitpid, pid, 0)[1]
def get_user(user): def get_user(user):
"Take either an username or an uid, and return a tuple (user, uid, gid)." "Take either an username or an uid, and return a tuple (user, uid, gid)."
...@@ -403,17 +404,6 @@ def get_user(user): ...@@ -403,17 +404,6 @@ def get_user(user):
# internal stuff, do not look! # internal stuff, do not look!
def _eintr_wrapper(f, *args):
"Wraps some callable with a loop that retries on EINTR"
while True:
try:
return f(*args)
except OSError, e: # pragma: no cover
if e.errno == errno.EINTR:
continue
else:
raise
try: try:
MAXFD = os.sysconf("SC_OPEN_MAX") MAXFD = os.sysconf("SC_OPEN_MAX")
except: # pragma: no cover except: # pragma: no cover
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment