Author: Joannah Nanjekye <[email protected]>
Branch: pread/pwrite
Changeset: r90387:c61e7a2fca32
Date: 2017-02-25 13:18 +0300
http://bitbucket.org/pypy/pypy/changeset/c61e7a2fca32/
Log: retry transparently when we get EINTR error
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -206,11 +206,18 @@
interpleveldefs['get_blocking'] = 'interp_posix.get_blocking'
interpleveldefs['set_blocking'] = 'interp_posix.set_blocking'
+ if hasattr(rposix, 'getpriority'):
+ interpleveldefs['getpriority'] = 'interp_posix.getpriority'
+ interpleveldefs['setpriority'] = 'interp_posix.setpriority'
+ for _name in ['PRIO_PROCESS', 'PRIO_PGRP', 'PRIO_USER']:
+ assert getattr(rposix, _name) is not None, "missing %r" % (_name,)
+ interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name)
+
if hasattr(rposix, 'pread'):
interpleveldefs['pread'] = 'interp_posix.pread'
if hasattr(rposix, 'pwrite'):
- interpleveldefs['pwrite'] = 'interp_posix.pwrite'
-
+ interpleveldefs['pwrite'] = 'interp_posix.pwrite'
+
for _name in ["O_CLOEXEC"]:
if getattr(rposix, _name) is not None:
interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name)
@@ -225,4 +232,9 @@
for constant in dir(os):
value = getattr(os, constant)
if constant.isupper() and type(value) is int:
+ if constant in ['SEEK_SET', 'SEEK_CUR', 'SEEK_END',
+ 'P_NOWAIT', 'P_NOWAITO', 'P_WAIT']:
+ # obscure, but these names are not in CPython's posix module
+ # and if we put it here then they end up twice in 'os.__all__'
+ continue
Module.interpleveldefs[constant] = "space.wrap(%s)" % value
diff --git a/pypy/module/posix/interp_posix.py
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -40,9 +40,9 @@
def wrap_uid(space, uid):
if uid <= r_uint(sys.maxint):
- return space.wrap(intmask(uid))
+ return space.newint(intmask(uid))
else:
- return space.wrap(uid) # an unsigned number
+ return space.newint(uid) # an unsigned number
wrap_gid = wrap_uid
class FileEncoder(object):
@@ -66,7 +66,7 @@
self.w_obj = w_obj
def as_bytes(self):
- return self.space.fsencode_w(self.w_obj)
+ return self.space.bytes0_w(self.w_obj)
def as_unicode(self):
return self.space.fsdecode_w(self.w_obj)
@@ -85,7 +85,7 @@
fname = FileEncoder(space, w_fname)
return func(fname, *args)
else:
- fname = space.fsencode_w(w_fname)
+ fname = space.bytes0_w(w_fname)
return func(fname, *args)
return dispatch
@@ -148,11 +148,15 @@
try:
path_b = space.fsencode_w(w_value)
return Path(-1, path_b, None, w_value)
- except OperationError:
+ except OperationError as e:
+ if not e.match(space, space.w_TypeError):
+ raise
if allow_fd:
fd = unwrap_fd(space, w_value, "string, bytes or integer")
return Path(fd, None, None, w_value)
- raise oefmt(space.w_TypeError, "illegal type for path parameter")
+ raise oefmt(space.w_TypeError,
+ "illegal type for path parameter (expected "
+ "string or bytes, got %T)", w_value)
class _PathOrFd(Unwrapper):
def unwrap(self, space, w_value):
@@ -226,16 +230,22 @@
If it is unavailable, using it will raise a NotImplementedError."""
if rposix.O_CLOEXEC is not None:
flags |= rposix.O_CLOEXEC
+ while True:
+ try:
+ if rposix.HAVE_OPENAT and dir_fd != DEFAULT_DIR_FD:
+ path = space.fsencode_w(w_path)
+ fd = rposix.openat(path, flags, mode, dir_fd)
+ else:
+ fd = dispatch_filename(rposix.open)(space, w_path, flags, mode)
+ break
+ except OSError as e:
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
try:
- if rposix.HAVE_OPENAT and dir_fd != DEFAULT_DIR_FD:
- path = space.fsencode_w(w_path)
- fd = rposix.openat(path, flags, mode, dir_fd)
- else:
- fd = dispatch_filename(rposix.open)(space, w_path, flags, mode)
_open_inhcache.set_non_inheritable(fd)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
- return space.wrap(fd)
+ rposix.c_close(fd)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
+ return space.newint(fd)
@unwrap_spec(fd=c_int, position=r_longlong, how=c_int)
def lseek(space, fd, position, how):
@@ -245,9 +255,9 @@
try:
pos = os.lseek(fd, position, how)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.wrap(pos)
+ return space.newint(pos)
@unwrap_spec(fd=c_int)
def isatty(space, fd):
@@ -256,19 +266,20 @@
try:
res = os.isatty(fd)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.wrap(res)
+ return space.newbool(res)
@unwrap_spec(fd=c_int, length=int)
def read(space, fd, length):
"""Read data from a file descriptor."""
- try:
- s = os.read(fd, length)
- except OSError as e:
- raise wrap_oserror(space, e)
- else:
- return space.newbytes(s)
+ while True:
+ try:
+ s = os.read(fd, length)
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ else:
+ return space.newbytes(s)
@unwrap_spec(fd=c_int)
def write(space, fd, w_data):
@@ -284,15 +295,19 @@
@unwrap_spec(fd=c_int, length=int, offset=int)
def pread(space, fd, length, offset):
+ """Read a string to a file descriptor at a given offset.
+ """
try:
s = rposix.pread(fd, length, offset)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=True)
else:
- return space.newbytes(s)
+ return space.newbytes(s)
@unwrap_spec(fd=c_int, offset=int)
def pwrite(space, fd, w_data, offset):
+ """Write a string to a file descriptor at a given offset.
+ """
data = space.getarg_w('y*', w_data)
try:
res = rposix.pwrite(fd, data.as_str(), offset)
@@ -304,10 +319,14 @@
@unwrap_spec(fd=c_int)
def close(space, fd):
"""Close a file descriptor (for low level IO)."""
+ # PEP 475 note: os.close() must not retry upon EINTR. Like in
+ # previous versions of Python it raises OSError in this case.
+ # The text of PEP 475 seems to suggest that EINTR is eaten and
+ # hidden from app-level, but it is not the case in CPython 3.5.2.
try:
os.close(fd)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(fd_low=c_int, fd_high=c_int)
def closerange(fd_low, fd_high):
@@ -317,10 +336,12 @@
@unwrap_spec(fd=c_int, length=r_longlong)
def ftruncate(space, fd, length):
"""Truncate a file (by file descriptor) to a specified length."""
- try:
- os.ftruncate(fd, length)
- except OSError as e:
- raise wrap_oserror(space, e)
+ while True:
+ try:
+ os.ftruncate(fd, length)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
def truncate(space, w_path, w_length):
"""Truncate a file to a specified length."""
@@ -330,7 +351,7 @@
if space.isinstance_w(w_path, space.w_int):
w_fd = w_path
else:
- w_fd = open(space, w_path, os.O_RDWR | os.O_CREAT)
+ w_fd = open(space, w_path, os.O_WRONLY)
allocated_fd = True
fd = space.c_filedescriptor_w(w_fd)
@@ -344,19 +365,23 @@
def fsync(space, w_fd):
"""Force write of file with filedescriptor to disk."""
fd = space.c_filedescriptor_w(w_fd)
- try:
- os.fsync(fd)
- except OSError as e:
- raise wrap_oserror(space, e)
+ while True:
+ try:
+ os.fsync(fd)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
def fdatasync(space, w_fd):
"""Force write of file with filedescriptor to disk.
Does not force update of metadata."""
fd = space.c_filedescriptor_w(w_fd)
- try:
- os.fdatasync(fd)
- except OSError as e:
- raise wrap_oserror(space, e)
+ while True:
+ try:
+ os.fdatasync(fd)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
def sync(space):
"""Force write of everything to disk."""
@@ -366,10 +391,12 @@
"""Change to the directory of the given file descriptor. fildes must be
opened on a directory, not a file."""
fd = space.c_filedescriptor_w(w_fd)
- try:
- os.fchdir(fd)
- except OSError as e:
- raise wrap_oserror(space, e)
+ while True:
+ try:
+ os.fchdir(fd)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
# ____________________________________________________________
@@ -386,7 +413,7 @@
if i < rposix_stat.N_INDEXABLE_FIELDS:
# get the first 10 items by indexing; this gives us
# 'st_Xtime' as an integer, too
- w_value = space.wrap(st[i])
+ w_value = space.newint(st[i])
lst[i] = w_value
else:
try:
@@ -396,8 +423,8 @@
assert name.startswith('nsec_')
value = rposix_stat.get_stat_ns_as_bigint(st, name[5:])
value = value.tolong() % 1000000000
- w_value = space.wrap(value)
- space.setitem(w_keywords, space.wrap(name), w_value)
+ w_value = space.newint(value)
+ space.setitem(w_keywords, space.newtext(name), w_value)
# Note: 'w_keywords' contains the three attributes 'nsec_Xtime'.
# We have an app-level property in app_posix.stat_result to
@@ -406,27 +433,27 @@
# non-rounded values for name-based access
if stat_float_times:
space.setitem(w_keywords,
- space.wrap('st_atime'), space.wrap(st.st_atime))
+ space.newtext('st_atime'), space.newfloat(st.st_atime))
space.setitem(w_keywords,
- space.wrap('st_mtime'), space.wrap(st.st_mtime))
+ space.newtext('st_mtime'), space.newfloat(st.st_mtime))
space.setitem(w_keywords,
- space.wrap('st_ctime'), space.wrap(st.st_ctime))
+ space.newtext('st_ctime'), space.newfloat(st.st_ctime))
#else:
# filled by the __init__ method
w_tuple = space.newtuple(lst)
w_stat_result = space.getattr(space.getbuiltinmodule(os.name),
- space.wrap('stat_result'))
+ space.newtext('stat_result'))
return space.call_function(w_stat_result, w_tuple, w_keywords)
def build_statvfs_result(space, st):
vals_w = [None] * len(rposix_stat.STATVFS_FIELDS)
for i, (name, _) in STATVFS_FIELDS:
- vals_w[i] = space.wrap(getattr(st, name))
+ vals_w[i] = space.newint(getattr(st, name))
w_tuple = space.newtuple(vals_w)
w_statvfs_result = space.getattr(
- space.getbuiltinmodule(os.name), space.wrap('statvfs_result'))
+ space.getbuiltinmodule(os.name), space.newtext('statvfs_result'))
return space.call_function(w_statvfs_result, w_tuple)
@@ -434,12 +461,13 @@
def fstat(space, fd):
"""Perform a stat system call on the file referenced to by an open
file descriptor."""
- try:
- st = rposix_stat.fstat(fd)
- except OSError as e:
- raise wrap_oserror(space, e)
- else:
- return build_stat_result(space, st)
+ while True:
+ try:
+ st = rposix_stat.fstat(fd)
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ else:
+ return build_stat_result(space, st)
@unwrap_spec(
path=path_or_fd(allow_fd=True),
@@ -485,7 +513,7 @@
raise oefmt(space.w_NotImplementedError,
"%s: unsupported argument combination", funcname)
except OSError as e:
- raise wrap_oserror2(space, e, path.w_path)
+ raise wrap_oserror2(space, e, path.w_path, eintr_retry=False)
else:
return build_stat_result(space, st)
@@ -515,19 +543,20 @@
state = space.fromcache(StatState)
if newval == -1:
- return space.wrap(state.stat_float_times)
+ return space.newbool(state.stat_float_times)
else:
state.stat_float_times = (newval != 0)
@unwrap_spec(fd=c_int)
def fstatvfs(space, fd):
- try:
- st = rposix_stat.fstatvfs(fd)
- except OSError as e:
- raise wrap_oserror(space, e)
- else:
- return build_statvfs_result(space, st)
+ while True:
+ try:
+ st = rposix_stat.fstatvfs(fd)
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ else:
+ return build_statvfs_result(space, st)
def statvfs(space, w_path):
@@ -543,7 +572,7 @@
rposix_stat.statvfs,
allow_fd_fn=rposix_stat.fstatvfs)(space, w_path)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
else:
return build_statvfs_result(space, st)
@@ -555,17 +584,19 @@
try:
newfd = rposix.dup(fd, inheritable=False)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.wrap(newfd)
+ return space.newint(newfd)
@unwrap_spec(fd=c_int, fd2=c_int, inheritable=bool)
def dup2(space, fd, fd2, inheritable=1):
"""Duplicate a file descriptor."""
+ # like os.close(), this can still raise EINTR to app-level in
+ # CPython 3.5.2
try:
rposix.dup2(fd, fd2, inheritable)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(mode=c_int,
dir_fd=DirFD(rposix.HAVE_FACCESSAT), effective_ids=bool,
@@ -610,9 +641,9 @@
else:
ok = dispatch_filename(rposix.access)(space, w_path, mode)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
else:
- return space.wrap(ok)
+ return space.newbool(ok)
def times(space):
@@ -624,13 +655,13 @@
try:
times = os.times()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.newtuple([space.wrap(times[0]),
- space.wrap(times[1]),
- space.wrap(times[2]),
- space.wrap(times[3]),
- space.wrap(times[4])])
+ return space.newtuple([space.newfloat(times[0]),
+ space.newfloat(times[1]),
+ space.newfloat(times[2]),
+ space.newfloat(times[3]),
+ space.newfloat(times[4])])
@unwrap_spec(command='fsencode')
def system(space, command):
@@ -638,9 +669,9 @@
try:
rc = os.system(command)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.wrap(rc)
+ return space.newint(rc)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
def unlink(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
@@ -659,7 +690,7 @@
else:
dispatch_filename(rposix.unlink)(space, w_path)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
def remove(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
@@ -678,7 +709,7 @@
else:
dispatch_filename(rposix.unlink)(space, w_path)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
def _getfullpathname(space, w_path):
"""helper for ntpath.abspath """
@@ -686,13 +717,13 @@
if space.isinstance_w(w_path, space.w_unicode):
path = FileEncoder(space, w_path)
fullpath = rposix.getfullpathname(path)
- w_fullpath = space.wrap(fullpath)
+ w_fullpath = space.newunicode(fullpath)
else:
- path = space.str0_w(w_path)
+ path = space.bytes0_w(w_path)
fullpath = rposix.getfullpathname(path)
w_fullpath = space.newbytes(fullpath)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
else:
return w_fullpath
@@ -701,7 +732,7 @@
try:
cur = os.getcwd()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
return space.newbytes(cur)
@@ -711,9 +742,9 @@
try:
cur = os.getcwdu()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
- return space.wrap(cur)
+ return space.newunicode(cur)
else:
def getcwd(space):
"""Return the current working directory as a string."""
@@ -728,7 +759,7 @@
else:
dispatch_filename(rposix.chdir)(space, w_path)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_MKDIRAT))
def mkdir(space, w_path, mode=0o777, __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
@@ -749,7 +780,7 @@
else:
dispatch_filename(rposix.mkdir)(space, w_path, mode)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
def rmdir(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
@@ -768,13 +799,13 @@
else:
dispatch_filename(rposix.rmdir)(space, w_path)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
@unwrap_spec(code=c_int)
def strerror(space, code):
"""Translate an error code to a message string."""
try:
- return space.wrap(_strerror(code))
+ return space.newunicode(_strerror(code))
except ValueError:
raise oefmt(space.w_ValueError, "strerror() argument out of range")
@@ -783,15 +814,15 @@
try:
cur = os.getlogin()
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap_fsdecoded(cur)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newfilename(cur)
# ____________________________________________________________
def getstatfields(space):
# for app_posix.py: export the list of 'st_xxx' names that we know
# about at RPython level
- return space.newlist([space.wrap(name) for _, (name, _) in STAT_FIELDS])
+ return space.newlist([space.newtext(name) for _, (name, _) in STAT_FIELDS])
class State:
@@ -823,7 +854,7 @@
for key, value in rwin32._wenviron_items():
if isinstance(key, str):
key = key.upper()
- space.setitem(w_env, space.wrap(key), space.wrap(value))
+ space.setitem(w_env, space.newtext(key), space.newtext(value))
@unwrap_spec(name=unicode, value=unicode)
def putenv(space, name, value):
@@ -836,7 +867,7 @@
try:
rwin32._wputenv(name, value)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
def _convertenviron(space, w_env):
for key, value in os.environ.items():
@@ -847,7 +878,7 @@
try:
dispatch_filename_2(rposix.putenv)(space, w_name, w_value)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def unsetenv(space, w_name):
"""Delete an environment variable."""
@@ -856,7 +887,7 @@
except KeyError:
pass
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def listdir(space, w_path=None):
@@ -875,11 +906,11 @@
if space.is_none(w_path):
w_path = space.newunicode(u".")
if space.isinstance_w(w_path, space.w_bytes):
- dirname = space.str0_w(w_path)
+ dirname = space.bytes0_w(w_path)
try:
result = rposix.listdir(dirname)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
return space.newlist_bytes(result)
try:
path = space.fsencode_w(w_path)
@@ -893,35 +924,35 @@
try:
result = rposix.fdlistdir(os.dup(fd))
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
dirname = FileEncoder(space, w_path)
try:
result = rposix.listdir(dirname)
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
len_result = len(result)
result_w = [None] * len_result
for i in range(len_result):
if _WIN32:
- result_w[i] = space.wrap(result[i])
+ result_w[i] = space.newunicode(result[i])
else:
- result_w[i] = space.wrap_fsdecoded(result[i])
+ result_w[i] = space.newfilename(result[i])
return space.newlist(result_w)
@unwrap_spec(fd=c_int)
def get_inheritable(space, fd):
try:
- return space.wrap(rposix.get_inheritable(fd))
+ return space.newbool(rposix.get_inheritable(fd))
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(fd=c_int, inheritable=int)
def set_inheritable(space, fd, inheritable):
try:
rposix.set_inheritable(fd, inheritable)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
_pipe_inhcache = rposix.SetNonInheritableCache()
@@ -929,19 +960,24 @@
"Create a pipe. Returns (read_end, write_end)."
try:
fd1, fd2 = rposix.pipe(rposix.O_CLOEXEC or 0)
+ except OSError as e:
+ raise wrap_oserror(space, e, eintr_retry=False)
+ try:
_pipe_inhcache.set_non_inheritable(fd1)
_pipe_inhcache.set_non_inheritable(fd2)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
+ rposix.c_close(fd2)
+ rposix.c_close(fd1)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newtuple([space.newint(fd1), space.newint(fd2)])
@unwrap_spec(flags=c_int)
def pipe2(space, flags):
try:
fd1, fd2 = rposix.pipe2(flags)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newtuple([space.newint(fd1), space.newint(fd2)])
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT),
follow_symlinks=bool)
@@ -966,11 +1002,12 @@
if not rposix.HAVE_FCHMODAT:
if not follow_symlinks:
raise argument_unavailable(space, "chmod", "follow_symlinks")
- try:
- dispatch_filename(rposix.chmod)(space, w_path, mode)
- return
- except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ while True:
+ try:
+ dispatch_filename(rposix.chmod)(space, w_path, mode)
+ return
+ except OSError as e:
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
try:
path = space.fsencode_w(w_path)
@@ -979,16 +1016,25 @@
raise oefmt(space.w_TypeError,
"argument should be string, bytes or integer, not %T", w_path)
fd = unwrap_fd(space, w_path)
- _chmod_fd(space, fd, mode)
- else:
+ # NB. in CPython 3.5.2, os.chmod(fd) propagates EINTR to app-level,
+ # but os.fchmod(fd) retries automatically. This might be fixed in
+ # more recent CPythons.
+ while True:
+ try:
+ os.fchmod(fd, mode)
+ return
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ while True:
try:
_chmod_path(path, mode, dir_fd, follow_symlinks)
+ break
except OSError as e:
if not follow_symlinks and e.errno in (ENOTSUP, EOPNOTSUPP):
# fchmodat() doesn't actually implement follow_symlinks=False
# so raise NotImplementedError in this case
raise argument_unavailable(space, "chmod", "follow_symlinks")
- raise wrap_oserror2(space, e, w_path)
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
def _chmod_path(path, mode, dir_fd, follow_symlinks):
if dir_fd != DEFAULT_DIR_FD or not follow_symlinks:
@@ -996,19 +1042,17 @@
else:
rposix.chmod(path, mode)
-def _chmod_fd(space, fd, mode):
- try:
- os.fchmod(fd, mode)
- except OSError as e:
- raise wrap_oserror(space, e)
-
-
@unwrap_spec(fd=c_int, mode=c_int)
def fchmod(space, fd, mode):
"""\
Change the access permissions of the file given by file descriptor fd.
"""
- _chmod_fd(space, fd, mode)
+ while True:
+ try:
+ os.fchmod(fd, mode)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
@unwrap_spec(src_dir_fd=DirFD(rposix.HAVE_RENAMEAT),
dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT))
@@ -1032,7 +1076,8 @@
else:
dispatch_filename_2(rposix.rename)(space, w_src, w_dst)
except OSError as e:
- raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst)
+ raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst,
+ eintr_retry=False)
@unwrap_spec(src_dir_fd=DirFD(rposix.HAVE_RENAMEAT),
dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT))
@@ -1056,7 +1101,8 @@
else:
dispatch_filename_2(rposix.replace)(space, w_src, w_dst)
except OSError as e:
- raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst)
+ raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst,
+ eintr_retry=False)
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_MKFIFOAT))
def mkfifo(space, w_path, mode=0666, __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
@@ -1068,14 +1114,18 @@
and path should be relative; path will then be relative to that directory.
dir_fd may not be implemented on your platform.
If it is unavailable, using it will raise a NotImplementedError."""
- try:
- if rposix.HAVE_MKFIFOAT and dir_fd != DEFAULT_DIR_FD:
- path = space.fsencode_w(w_path)
- rposix.mkfifoat(path, mode, dir_fd)
- else:
- dispatch_filename(rposix.mkfifo)(space, w_path, mode)
- except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ # CPython 3.5.2: why does os.mkfifo() retry automatically if it
+ # gets EINTR, but not os.mkdir()?
+ while True:
+ try:
+ if rposix.HAVE_MKFIFOAT and dir_fd != DEFAULT_DIR_FD:
+ path = space.fsencode_w(w_path)
+ rposix.mkfifoat(path, mode, dir_fd)
+ else:
+ dispatch_filename(rposix.mkfifo)(space, w_path, mode)
+ break
+ except OSError as e:
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
@unwrap_spec(mode=c_int, device=c_int, dir_fd=DirFD(rposix.HAVE_MKNODAT))
def mknod(space, w_path, mode=0600, device=0,
@@ -1093,28 +1143,30 @@
and path should be relative; path will then be relative to that directory.
dir_fd may not be implemented on your platform.
If it is unavailable, using it will raise a NotImplementedError."""
- try:
- if rposix.HAVE_MKNODAT and dir_fd != DEFAULT_DIR_FD:
- fname = space.fsencode_w(w_path)
- rposix.mknodat(fname, mode, device, dir_fd)
- else:
- dispatch_filename(rposix.mknod)(space, w_path, mode, device)
- except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ while True:
+ try:
+ if rposix.HAVE_MKNODAT and dir_fd != DEFAULT_DIR_FD:
+ fname = space.fsencode_w(w_path)
+ rposix.mknodat(fname, mode, device, dir_fd)
+ else:
+ dispatch_filename(rposix.mknod)(space, w_path, mode, device)
+ break
+ except OSError as e:
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
@unwrap_spec(mask=c_int)
def umask(space, mask):
"Set the current numeric umask and return the previous umask."
prevmask = os.umask(mask)
- return space.wrap(prevmask)
+ return space.newint(prevmask)
def getpid(space):
"Return the current process id."
try:
pid = os.getpid()
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(pid)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(pid)
@unwrap_spec(pid=c_int, signal=c_int)
def kill(space, pid, signal):
@@ -1122,7 +1174,7 @@
try:
rposix.kill(pid, signal)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(pgid=c_int, signal=c_int)
def killpg(space, pgid, signal):
@@ -1130,7 +1182,7 @@
try:
os.killpg(pgid, signal)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def abort(space):
"""Abort the interpreter immediately. This 'dumps core' or otherwise fails
@@ -1139,11 +1191,9 @@
rposix.kill(os.getpid(), signal.SIGABRT)
@unwrap_spec(
- src='fsencode', dst='fsencode', # <- simpler: link() is never on Windows
src_dir_fd=DirFD(rposix.HAVE_LINKAT), dst_dir_fd=DirFD(rposix.HAVE_LINKAT),
follow_symlinks=bool)
-def link(
- space, src, dst, __kwonly__,
+def link(space, w_src, w_dst, __kwonly__,
src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD,
follow_symlinks=True):
"""\
@@ -1160,6 +1210,8 @@
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
platform. If they are unavailable, using them will raise a
NotImplementedError."""
+ src = space.fsencode_w(w_src)
+ dst = space.fsencode_w(w_dst)
try:
if (rposix.HAVE_LINKAT and
(src_dir_fd != DEFAULT_DIR_FD or dst_dir_fd != DEFAULT_DIR_FD
@@ -1168,7 +1220,8 @@
else:
rposix.link(src, dst)
except OSError as e:
- raise wrap_oserror(space, e, filename=src, filename2=dst)
+ raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst,
+ eintr_retry=False)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_SYMLINKAT))
@@ -1195,7 +1248,8 @@
else:
dispatch_filename_2(rposix.symlink)(space, w_src, w_dst)
except OSError as e:
- raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst)
+ raise wrap_oserror2(space, e, w_filename=w_src, w_filename2=w_dst,
+ eintr_retry=False)
@unwrap_spec(
@@ -1216,7 +1270,7 @@
else:
result = call_rposix(rposix.readlink, path)
except OSError as e:
- raise wrap_oserror2(space, e, path.w_path)
+ raise wrap_oserror2(space, e, path.w_path, eintr_retry=False)
w_result = space.newbytes(result)
if space.isinstance_w(path.w_path, space.w_unicode):
return space.fsdecode(w_result)
@@ -1264,7 +1318,7 @@
except:
# Don't clobber the OSError if the fork failed
pass
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
if pid == 0:
run_fork_hooks('child', space)
else:
@@ -1273,22 +1327,27 @@
def fork(space):
pid, irrelevant = _run_forking_function(space, "F")
- return space.wrap(pid)
+ return space.newint(pid)
def openpty(space):
"Open a pseudo-terminal, returning open fd's for both master and slave
end."
+ master_fd = slave_fd = -1
try:
master_fd, slave_fd = os.openpty()
rposix.set_inheritable(master_fd, False)
rposix.set_inheritable(slave_fd, False)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.newtuple([space.wrap(master_fd), space.wrap(slave_fd)])
+ if master_fd >= 0:
+ rposix.c_close(master_fd)
+ if slave_fd >= 0:
+ rposix.c_close(slave_fd)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newtuple([space.newint(master_fd), space.newint(slave_fd)])
def forkpty(space):
pid, master_fd = _run_forking_function(space, "P")
- return space.newtuple([space.wrap(pid),
- space.wrap(master_fd)])
+ return space.newtuple([space.newint(pid),
+ space.newint(master_fd)])
@unwrap_spec(pid=c_int, options=c_int)
def waitpid(space, pid, options):
@@ -1296,11 +1355,15 @@
Wait for completion of a given child process.
"""
- try:
- pid, status = os.waitpid(pid, options)
- except OSError as e:
- raise wrap_oserror(space, e)
- return space.newtuple([space.wrap(pid), space.wrap(status)])
+ while True:
+ try:
+ pid, status = os.waitpid(pid, options)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ return space.newtuple([space.newint(pid), space.newint(status)])
+
+# missing: waitid()
@unwrap_spec(status=c_int)
def _exit(space, status):
@@ -1329,7 +1392,7 @@
try:
os.execv(command, args)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def _env2interp(space, w_env):
@@ -1374,12 +1437,12 @@
try:
rposix.fexecve(fd, args, env)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
try:
os.execve(path, args, env)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(mode=int, path='fsencode')
def spawnv(space, mode, path, w_argv):
@@ -1387,8 +1450,8 @@
try:
ret = os.spawnv(mode, path, args)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(ret)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(ret)
@unwrap_spec(mode=int, path='fsencode')
def spawnve(space, mode, path, w_argv, w_env):
@@ -1397,8 +1460,8 @@
try:
ret = os.spawnve(mode, path, args, env)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(ret)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(ret)
@unwrap_spec(
@@ -1505,7 +1568,7 @@
# something is wrong with the file, when it also
# could be the time stamp that gives a problem. */
# so we use wrap_oserror() instead of wrap_oserror2() here
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@specialize.arg(1)
def do_utimes(space, func, arg, utime):
@@ -1522,7 +1585,7 @@
func(arg, (atime, mtime))
except OSError as e:
# see comment above: don't use wrap_oserror2()
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@specialize.argtype(1)
def _dispatch_utime(path, times):
@@ -1549,7 +1612,7 @@
return time, 0
def convert_ns(space, w_ns_time):
- w_billion = space.wrap(1000000000)
+ w_billion = space.newint(1000000000)
w_res = space.divmod(w_ns_time, w_billion)
res_w = space.fixedview(w_res)
time_int = space.int_w(res_w[0])
@@ -1565,12 +1628,12 @@
try:
r = os.uname()
except OSError as e:
- raise wrap_oserror(space, e)
- l_w = [space.wrap_fsdecoded(i)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ l_w = [space.newfilename(i)
for i in [r[0], r[1], r[2], r[3], r[4]]]
w_tuple = space.newtuple(l_w)
w_uname_result = space.getattr(space.getbuiltinmodule(os.name),
- space.wrap('uname_result'))
+ space.newtext('uname_result'))
return space.call_function(w_uname_result, w_tuple)
def getuid(space):
@@ -1589,7 +1652,7 @@
try:
os.setuid(uid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(euid=c_uid_t)
def seteuid(space, euid):
@@ -1600,7 +1663,7 @@
try:
os.seteuid(euid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(gid=c_gid_t)
def setgid(space, gid):
@@ -1611,7 +1674,7 @@
try:
os.setgid(gid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(egid=c_gid_t)
def setegid(space, egid):
@@ -1622,18 +1685,18 @@
try:
os.setegid(egid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
-@unwrap_spec(path='fsencode')
-def chroot(space, path):
+def chroot(space, w_path):
""" chroot(path)
Change root directory to path.
"""
+ path = space.fsencode_w(w_path)
try:
os.chroot(path)
except OSError as e:
- raise wrap_oserror(space, e, path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
return space.w_None
def getgid(space):
@@ -1665,7 +1728,7 @@
try:
list = os.getgroups()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.newlist([wrap_gid(space, e) for e in list])
def setgroups(space, w_groups):
@@ -1679,9 +1742,9 @@
try:
os.setgroups(list[:])
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
-@unwrap_spec(username=str, gid=c_gid_t)
+@unwrap_spec(username='text', gid=c_gid_t)
def initgroups(space, username, gid):
""" initgroups(username, gid) -> None
@@ -1692,14 +1755,14 @@
try:
os.initgroups(username, gid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def getpgrp(space):
""" getpgrp() -> pgrp
Return the current process group id.
"""
- return space.wrap(os.getpgrp())
+ return space.newint(os.getpgrp())
def setpgrp(space):
""" setpgrp()
@@ -1709,7 +1772,7 @@
try:
os.setpgrp()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.w_None
def getppid(space):
@@ -1717,7 +1780,7 @@
Return the parent's process id.
"""
- return space.wrap(os.getppid())
+ return space.newint(os.getppid())
@unwrap_spec(pid=c_int)
def getpgid(space, pid):
@@ -1728,8 +1791,8 @@
try:
pgid = os.getpgid(pid)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(pgid)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(pgid)
@unwrap_spec(pid=c_int, pgrp=c_int)
def setpgid(space, pid, pgrp):
@@ -1740,7 +1803,7 @@
try:
os.setpgid(pid, pgrp)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.w_None
@unwrap_spec(ruid=c_uid_t, euid=c_uid_t)
@@ -1752,7 +1815,7 @@
try:
os.setreuid(ruid, euid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(rgid=c_gid_t, egid=c_gid_t)
def setregid(space, rgid, egid):
@@ -1763,7 +1826,7 @@
try:
os.setregid(rgid, egid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(pid=c_int)
def getsid(space, pid):
@@ -1774,8 +1837,8 @@
try:
sid = os.getsid(pid)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(sid)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(sid)
def setsid(space):
""" setsid()
@@ -1785,7 +1848,7 @@
try:
os.setsid()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.w_None
@unwrap_spec(fd=c_int)
@@ -1797,8 +1860,8 @@
try:
pgid = os.tcgetpgrp(fd)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(pgid)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(pgid)
@unwrap_spec(fd=c_int, pgid=c_gid_t)
def tcsetpgrp(space, fd, pgid):
@@ -1809,7 +1872,7 @@
try:
os.tcsetpgrp(fd, pgid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def getresuid(space):
""" getresuid() -> (ruid, euid, suid)
@@ -1819,7 +1882,7 @@
try:
(ruid, euid, suid) = os.getresuid()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.newtuple([wrap_uid(space, ruid),
wrap_uid(space, euid),
wrap_uid(space, suid)])
@@ -1832,7 +1895,7 @@
try:
(rgid, egid, sgid) = os.getresgid()
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.newtuple([wrap_gid(space, rgid),
wrap_gid(space, egid),
wrap_gid(space, sgid)])
@@ -1846,7 +1909,7 @@
try:
os.setresuid(ruid, euid, suid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
@unwrap_spec(rgid=c_gid_t, egid=c_gid_t, sgid=c_gid_t)
def setresgid(space, rgid, egid, sgid):
@@ -1857,13 +1920,36 @@
try:
os.setresgid(rgid, egid, sgid)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
+
+@unwrap_spec(which=int, who=int)
+def getpriority(space, which, who):
+ """ getpriority(which, who) -> int
+
+ Get program scheduling priority.
+ """
+ try:
+ returned_priority = rposix.getpriority(which, who)
+ except OSError as e:
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(returned_priority)
+
+@unwrap_spec(which=int, who=int, priority=int)
+def setpriority(space, which, who, priority):
+ """ setpriority(which, who, priority)
+
+ Set program scheduling priority.
+ """
+ try:
+ rposix.setpriority(which, who, priority)
+ except OSError as e:
+ raise wrap_oserror(space, e, eintr_retry=False)
def declare_new_w_star(name):
if name in ('WEXITSTATUS', 'WSTOPSIG', 'WTERMSIG'):
@unwrap_spec(status=c_int)
def WSTAR(space, status):
- return space.wrap(getattr(os, name)(status))
+ return space.newint(getattr(os, name)(status))
else:
@unwrap_spec(status=c_int)
def WSTAR(space, status):
@@ -1881,16 +1967,16 @@
@unwrap_spec(fd=c_int)
def ttyname(space, fd):
try:
- return space.wrap_fsdecoded(os.ttyname(fd))
+ return space.newfilename(os.ttyname(fd))
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
def confname_w(space, w_name, namespace):
# XXX slightly non-nice, reuses the sysconf of the underlying os module
if space.isinstance_w(w_name, space.w_unicode):
try:
- num = namespace[space.str_w(w_name)]
+ num = namespace[space.text_w(w_name)]
except KeyError:
raise oefmt(space.w_ValueError, "unrecognized configuration name")
else:
@@ -1902,8 +1988,8 @@
try:
res = os.sysconf(num)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(res)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(res)
@unwrap_spec(fd=c_int)
def fpathconf(space, fd, w_name):
@@ -1911,8 +1997,8 @@
try:
res = os.fpathconf(fd, num)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(res)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(res)
@unwrap_spec(path=path_or_fd(allow_fd=hasattr(os, 'fpathconf')))
def pathconf(space, path, w_name):
@@ -1921,21 +2007,21 @@
try:
res = os.fpathconf(path.as_fd, num)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
else:
try:
res = os.pathconf(path.as_bytes, num)
except OSError as e:
- raise wrap_oserror2(space, e, path.w_path)
- return space.wrap(res)
+ raise wrap_oserror2(space, e, path.w_path, eintr_retry=False)
+ return space.newint(res)
def confstr(space, w_name):
num = confname_w(space, w_name, os.confstr_names)
try:
res = os.confstr(num)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(res)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newtext(res)
@unwrap_spec(
uid=c_uid_t, gid=c_gid_t,
@@ -1975,11 +2061,16 @@
if not follow_symlinks:
raise oefmt(space.w_ValueError,
"chown: cannnot use fd and follow_symlinks together")
- try:
- os.fchown(fd, uid, gid)
- except OSError as e:
- raise wrap_oserror(space, e)
- else:
+ # NB. in CPython 3.5.2, os.chown(fd) propagates EINTR to app-level,
+ # but os.fchown(fd) retries automatically. This might be fixed in
+ # more recent CPythons.
+ while True:
+ try:
+ os.fchown(fd, uid, gid)
+ return
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ while True:
# String case
try:
if (rposix.HAVE_LCHOWN and
@@ -1992,21 +2083,23 @@
assert follow_symlinks
assert dir_fd == DEFAULT_DIR_FD
os.chown(path, uid, gid)
+ break
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
+ wrap_oserror2(space, e, w_path, eintr_retry=True)
-@unwrap_spec(path='fsencode', uid=c_uid_t, gid=c_gid_t)
-def lchown(space, path, uid, gid):
+@unwrap_spec(uid=c_uid_t, gid=c_gid_t)
+def lchown(space, w_path, uid, gid):
"""lchown(path, uid, gid)
Change the owner and group id of path to the numeric uid and gid.
This function will not follow symbolic links.
Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."""
+ path = space.fsencode_w(w_path)
try:
os.lchown(path, uid, gid)
except OSError as e:
- raise wrap_oserror(space, e, path)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
@unwrap_spec(uid=c_uid_t, gid=c_gid_t)
def fchown(space, w_fd, uid, gid):
@@ -2015,34 +2108,36 @@
Change the owner and group id of the file given by file descriptor
fd to the numeric uid and gid. Equivalent to os.chown(fd, uid, gid)."""
fd = space.c_filedescriptor_w(w_fd)
- try:
- os.fchown(fd, uid, gid)
- except OSError as e:
- raise wrap_oserror(space, e)
+ while True:
+ try:
+ os.fchown(fd, uid, gid)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
def getloadavg(space):
try:
load = os.getloadavg()
except OSError:
raise oefmt(space.w_OSError, "Load averages are unobtainable")
- return space.newtuple([space.wrap(load[0]),
- space.wrap(load[1]),
- space.wrap(load[2])])
+ return space.newtuple([space.newfloat(load[0]),
+ space.newfloat(load[1]),
+ space.newfloat(load[2])])
@unwrap_spec(major=c_int, minor=c_int)
def makedev(space, major, minor):
result = os.makedev(major, minor)
- return space.wrap(result)
+ return space.newint(result)
@unwrap_spec(device="c_uint")
def major(space, device):
result = os.major(intmask(device))
- return space.wrap(result)
+ return space.newint(result)
@unwrap_spec(device="c_uint")
def minor(space, device):
result = os.minor(intmask(device))
- return space.wrap(result)
+ return space.newint(result)
@unwrap_spec(increment=c_int)
def nice(space, increment):
@@ -2051,8 +2146,14 @@
try:
res = os.nice(increment)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.wrap(res)
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newint(res)
+
+class SigCheck:
+ pass
+_sigcheck = SigCheck()
+def _signal_checker():
+ _sigcheck.space.getexecutioncontext().checksignals()
@unwrap_spec(size=int)
def urandom(space, size):
@@ -2062,16 +2163,22 @@
"""
context = get(space).random_context
try:
- return space.newbytes(rurandom.urandom(context, size))
+ # urandom() takes a final argument that should be a regular function,
+ # not a bound method like 'getexecutioncontext().checksignals'.
+ # Otherwise, we can't use it from several independent places.
+ _sigcheck.space = space
+ return space.newbytes(rurandom.urandom(context, n, _signal_checker))
except OSError as e:
- raise wrap_oserror(space, e)
+ # 'rurandom' should catch and retry internally if it gets EINTR
+ # (at least in os.read(), which is probably enough in practice)
+ raise wrap_oserror(space, e, eintr_retry=False)
def ctermid(space):
"""ctermid() -> string
Return the name of the controlling terminal for this process.
"""
- return space.wrap_fsdecoded(os.ctermid())
+ return space.newfilename(os.ctermid())
@unwrap_spec(fd=c_int)
def device_encoding(space, fd):
@@ -2084,14 +2191,14 @@
return space.w_None
if _WIN32:
if fd == 0:
- return space.wrap('cp%d' % rwin32.GetConsoleCP())
+ return space.newtext('cp%d' % rwin32.GetConsoleCP())
if fd in (1, 2):
- return space.wrap('cp%d' % rwin32.GetConsoleOutputCP())
+ return space.newtext('cp%d' % rwin32.GetConsoleOutputCP())
from rpython.rlib import rlocale
if rlocale.HAVE_LANGINFO:
codeset = rlocale.nl_langinfo(rlocale.CODESET)
if codeset:
- return space.wrap(codeset)
+ return space.newtext(codeset)
return space.w_None
if _WIN32:
@@ -2102,10 +2209,10 @@
try:
info = nt._getfileinformation(fd)
except OSError as e:
- raise wrap_oserror(space, e)
- return space.newtuple([space.wrap(info[0]),
- space.wrap(info[1]),
- space.wrap(info[2])])
+ raise wrap_oserror(space, e, eintr_retry=False)
+ return space.newtuple([space.newint(info[0]),
+ space.newint(info[1]),
+ space.newint(info[2])])
def _getfinalpathname(space, w_path):
path = space.unicode_w(w_path)
@@ -2113,10 +2220,10 @@
result = nt._getfinalpathname(path)
except nt.LLNotImplemented as e:
raise OperationError(space.w_NotImplementedError,
- space.wrap(e.msg))
+ space.newtext(e.msg))
except OSError as e:
- raise wrap_oserror2(space, e, w_path)
- return space.wrap(result)
+ raise wrap_oserror2(space, e, w_path, eintr_retry=False)
+ return space.newunicode(result)
def chflags():
@@ -2219,20 +2326,20 @@
success = rwin32.GetConsoleScreenBufferInfo(handle, buffer_info)
if not success:
raise rwin32.lastSavedWindowsError()
- w_columns = space.wrap(r_int(buffer_info.c_srWindow.c_Right) -
r_int(buffer_info.c_srWindow.c_Left) + 1)
- w_lines = space.wrap(r_int(buffer_info.c_srWindow.c_Bottom) -
r_int(buffer_info.c_srWindow.c_Top) + 1)
+ w_columns = space.newint(r_int(buffer_info.c_srWindow.c_Right) -
r_int(buffer_info.c_srWindow.c_Left) + 1)
+ w_lines = space.newint(r_int(buffer_info.c_srWindow.c_Bottom) -
r_int(buffer_info.c_srWindow.c_Top) + 1)
else:
with lltype.scoped_alloc(rposix.WINSIZE) as winsize:
failed = rposix.c_ioctl_voidp(fd, rposix.TIOCGWINSZ, winsize)
if failed:
raise exception_from_saved_errno(space, space.w_OSError)
- w_columns = space.wrap(r_uint(winsize.c_ws_col))
- w_lines = space.wrap(r_uint(winsize.c_ws_row))
+ w_columns = space.newint(r_uint(winsize.c_ws_col))
+ w_lines = space.newint(r_uint(winsize.c_ws_row))
w_tuple = space.newtuple([w_columns, w_lines])
w_terminal_size = space.getattr(space.getbuiltinmodule(os.name),
- space.wrap('terminal_size'))
+ space.newtext('terminal_size'))
return space.call_function(w_terminal_size, w_tuple)
@@ -2240,14 +2347,14 @@
count = rposix.cpu_count()
if count <= 0:
return space.w_None
- return space.wrap(count)
+ return space.newint(count)
@unwrap_spec(fd=c_int)
def get_blocking(space, fd):
try:
flags = rposix.get_status_flags(fd)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
return space.newbool(flags & rposix.O_NONBLOCK == 0)
@unwrap_spec(fd=c_int, blocking=int)
@@ -2260,4 +2367,4 @@
flags |= rposix.O_NONBLOCK
rposix.set_status_flags(fd, flags)
except OSError as e:
- raise wrap_oserror(space, e)
+ raise wrap_oserror(space, e, eintr_retry=False)
diff --git a/pypy/module/posix/test/test_posix2.py
b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -7,6 +7,7 @@
from rpython.tool.udir import udir
from pypy.tool.pytest.objspace import gettestobjspace
+from pypy.interpreter.gateway import interp2app
from rpython.translator.c.test.test_extfunc import need_sparse_files
from rpython.rlib import rposix
@@ -201,6 +202,8 @@
excinfo = raises(TypeError, self.posix.stat, 2.)
assert "should be string, bytes or integer, not float" in
str(excinfo.value)
raises(ValueError, self.posix.stat, -1)
+ raises(ValueError, self.posix.stat, b"abc\x00def")
+ raises(ValueError, self.posix.stat, u"abc\x00def")
if hasattr(__import__(os.name), "statvfs"):
def test_statvfs(self):
@@ -359,11 +362,11 @@
pdir = self.pdir + '/file1'
posix = self.posix
- assert posix.access(pdir, posix.R_OK)
- assert posix.access(pdir, posix.W_OK)
+ assert posix.access(pdir, posix.R_OK) is True
+ assert posix.access(pdir, posix.W_OK) is True
import sys
if sys.platform != "win32":
- assert not posix.access(pdir, posix.X_OK)
+ assert posix.access(pdir, posix.X_OK) is False
def test_times(self):
"""
@@ -839,7 +842,7 @@
fd = os.open(self.path2 + 'test_os_pread', os.O_RDWR | os.O_CREAT)
try:
os.write(fd, b'test')
- os.lseek(fd, 0, os.SEEK_SET)
+ os.lseek(fd, 0, 0)
assert os.pread(fd, 2, 1) == b'es'
assert os.read(fd, 2) == b'te'
finally:
@@ -851,7 +854,7 @@
fd = os.open(self.path2 + 'test_os_pwrite', os.O_RDWR | os.O_CREAT)
try:
os.write(fd, b'test')
- os.lseek(fd, 0, os.SEEK_SET)
+ os.lseek(fd, 0, 0)
os.pwrite(fd, b'xx', 1)
assert os.read(fd, 4) == b'txxt'
finally:
@@ -874,6 +877,31 @@
assert st.st_size == 10000000000
test_largefile.need_sparse_files = True
+ if hasattr(rposix, 'getpriority'):
+ def test_os_set_get_priority(self):
+ posix, os = self.posix, self.os
+ childpid = os.fork()
+ if childpid == 0:
+ # in the child (avoids changing the priority of the parent
+ # process)
+ orig_priority = posix.getpriority(posix.PRIO_PROCESS,
+ os.getpid())
+ orig_grp_priority = posix.getpriority(posix.PRIO_PGRP,
+ os.getpgrp())
+ posix.setpriority(posix.PRIO_PROCESS, os.getpid(),
+ orig_priority + 1)
+ new_priority = posix.getpriority(posix.PRIO_PROCESS,
+ os.getpid())
+ assert new_priority == orig_priority + 1
+ assert posix.getpriority(posix.PRIO_PGRP, os.getpgrp()) == (
+ orig_grp_priority)
+ os._exit(0) # ok
+ #
+ pid1, status1 = os.waitpid(childpid, 0)
+ assert pid1 == childpid
+ assert os.WIFEXITED(status1)
+ assert os.WEXITSTATUS(status1) == 0 # else, test failure
+
def test_write_buffer(self):
os = self.posix
fd = os.open(self.path2 + 'test_write_buffer',
@@ -1090,6 +1118,10 @@
posix.truncate(dest, 1)
assert 1 == posix.stat(dest).st_size
+ # File does not exist
+ e = raises(OSError, posix.truncate, dest + '-DOESNT-EXIST', 0)
+ assert e.value.filename == dest + '-DOESNT-EXIST'
+
try:
os.getlogin()
except (AttributeError, OSError):
@@ -1389,3 +1421,40 @@
if os.name == 'posix':
assert os.open in os.supports_dir_fd # openat()
+
+class AppTestPep475Retry:
+ spaceconfig = {'usemodules': USEMODULES}
+
+ def setup_class(cls):
+ if os.name != 'posix':
+ skip("xxx tests are posix-only")
+ if cls.runappdirect:
+ skip("xxx does not work with -A")
+
+ def fd_data_after_delay(space):
+ g = os.popen("sleep 5 && echo hello", "r")
+ cls._keepalive_g = g
+ return space.wrap(g.fileno())
+
+ cls.w_posix = space.appexec([], GET_POSIX)
+ cls.w_fd_data_after_delay = cls.space.wrap(
+ interp2app(fd_data_after_delay))
+
+ def test_pep475_retry_read(self):
+ import _signal as signal
+ signalled = []
+
+ def foo(*args):
+ signalled.append("ALARM")
+
+ signal.signal(signal.SIGALRM, foo)
+ try:
+ fd = self.fd_data_after_delay()
+ signal.alarm(1)
+ got = self.posix.read(fd, 100)
+ self.posix.close(fd)
+ finally:
+ signal.signal(signal.SIGALRM, signal.SIG_DFL)
+
+ assert signalled != []
+ assert got.startswith(b'h')
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -234,6 +234,7 @@
_ptyh = 'pty.h'
includes = ['unistd.h', 'sys/types.h', 'sys/wait.h',
'utime.h', 'sys/time.h', 'sys/times.h',
+ 'sys/resource.h',
'grp.h', 'dirent.h', 'sys/stat.h', 'fcntl.h',
'signal.h', 'sys/utsname.h', _ptyh]
if sys.platform.startswith('freebsd'):
@@ -249,6 +250,9 @@
SEEK_SET = rffi_platform.DefinedConstantInteger('SEEK_SET')
SEEK_CUR = rffi_platform.DefinedConstantInteger('SEEK_CUR')
SEEK_END = rffi_platform.DefinedConstantInteger('SEEK_END')
+ PRIO_PROCESS = rffi_platform.DefinedConstantInteger('PRIO_PROCESS')
+ PRIO_PGRP = rffi_platform.DefinedConstantInteger('PRIO_PGRP')
+ PRIO_USER = rffi_platform.DefinedConstantInteger('PRIO_USER')
O_NONBLOCK = rffi_platform.DefinedConstantInteger('O_NONBLOCK')
OFF_T = rffi_platform.SimpleType('off_t')
OFF_T_SIZE = rffi_platform.SizeOf('off_t')
@@ -262,6 +266,7 @@
if not _WIN32:
UID_T = rffi_platform.SimpleType('uid_t', rffi.UINT)
GID_T = rffi_platform.SimpleType('gid_t', rffi.UINT)
+ ID_T = rffi_platform.SimpleType('id_t', rffi.UINT)
TIOCGWINSZ = rffi_platform.DefinedConstantInteger('TIOCGWINSZ')
TMS = rffi_platform.Struct(
@@ -1760,6 +1765,22 @@
def setresgid(rgid, egid, sgid):
handle_posix_error('setresgid', c_setresgid(rgid, egid, sgid))
+ c_getpriority = external('getpriority', [rffi.INT, ID_T], rffi.INT,
+ save_err=rffi.RFFI_FULL_ERRNO_ZERO)
+ c_setpriority = external('setpriority', [rffi.INT, ID_T, rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
+
+ def getpriority(which, who):
+ result = widen(c_getpriority(which, who))
+ error = get_saved_errno()
+ if error != 0:
+ raise OSError(error, 'getpriority failed')
+ return result
+
+ def setpriority(which, who, prio):
+ handle_posix_error('setpriority', c_setpriority(which, who, prio))
+
+
#___________________________________________________________________
c_chroot = external('chroot', [rffi.CCHARP], rffi.INT,
@@ -1804,25 +1825,23 @@
finally:
lltype.free(l_utsbuf, flavor='raw')
-# These are actually macros on some/most systems
-c_makedev = external('makedev', [rffi.INT, rffi.INT], rffi.INT)
-c_major = external('major', [rffi.INT], rffi.INT)
-c_minor = external('minor', [rffi.INT], rffi.INT)
+if sys.platform != 'win32':
+ # These are actually macros on some/most systems
+ c_makedev = external('makedev', [rffi.INT, rffi.INT], rffi.INT, macro=True)
+ c_major = external('major', [rffi.INT], rffi.INT, macro=True)
+ c_minor = external('minor', [rffi.INT], rffi.INT, macro=True)
-@replace_os_function('makedev')
[email protected]_look_inside
-def makedev(maj, min):
- return c_makedev(maj, min)
+ @replace_os_function('makedev')
+ def makedev(maj, min):
+ return c_makedev(maj, min)
-@replace_os_function('major')
[email protected]_look_inside
-def major(dev):
- return c_major(dev)
+ @replace_os_function('major')
+ def major(dev):
+ return c_major(dev)
-@replace_os_function('minor')
[email protected]_look_inside
-def minor(dev):
- return c_minor(dev)
+ @replace_os_function('minor')
+ def minor(dev):
+ return c_minor(dev)
#___________________________________________________________________
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit