Author: Armin Rigo <[email protected]>
Branch: py3.5-noninherit
Changeset: r86553:bbc604db574e
Date: 2016-08-26 14:46 +0200
http://bitbucket.org/pypy/pypy/changeset/bbc604db574e/
Log: Make pipe() return non-inheritable fds using the now-official way.
Add pipe2().
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
@@ -76,6 +76,8 @@
'device_encoding': 'interp_posix.device_encoding',
'scandir': 'interp_scandir.scandir',
+ 'get_inheritable': 'interp_posix.get_inheritable',
+ 'set_inheritable': 'interp_posix.set_inheritable',
}
if hasattr(os, 'chown'):
@@ -193,6 +195,9 @@
interpleveldefs['_have_functions'] = (
'space.newlist([space.wrap(x) for x in interp_posix.have_functions])')
+ if rposix.HAVE_PIPE2:
+ interpleveldefs['pipe2'] = 'interp_posix.pipe2'
+
def startup(self, space):
from pypy.module.posix import interp_posix
from pypy.module.imp import importing
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
@@ -889,15 +889,32 @@
result_w[i] = space.fsdecode(w_bytes)
return space.newlist(result_w)
+@unwrap_spec(fd=c_int)
+def get_inheritable(space, fd):
+ return space.wrap(rposix.get_inheritable(fd))
+
+@unwrap_spec(fd=c_int, inheritable=int)
+def set_inheritable(space, fd, inheritable):
+ rposix.set_inheritable(fd, inheritable)
+
+_pipe_inhcache = rposix.SetNonInheritableCache()
+
def pipe(space):
"Create a pipe. Returns (read_end, write_end)."
try:
- fd1, fd2 = os.pipe()
+ fd1, fd2 = rposix.pipe(rposix.O_CLOEXEC or 0)
+ _pipe_inhcache.set_non_inheritable(fd1)
+ _pipe_inhcache.set_non_inheritable(fd2)
except OSError as e:
raise wrap_oserror(space, e)
- # XXX later, use rposix.pipe2() if available!
- rposix.set_inheritable(fd1, False)
- rposix.set_inheritable(fd2, False)
+ return space.newtuple([space.wrap(fd1), space.wrap(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)])
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT),
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
@@ -1077,6 +1077,33 @@
x = f.read(1)
assert x == 'e'
+ def test_pipe_inheritable(self):
+ fd1, fd2 = self.posix.pipe()
+ assert self.posix.get_inheritable(fd1) == False
+ assert self.posix.get_inheritable(fd2) == False
+ self.posix.close(fd1)
+ self.posix.close(fd2)
+
+ def test_pipe2(self):
+ if not hasattr(self.posix, 'pipe2'):
+ skip("no pipe2")
+ fd1, fd2 = self.posix.pipe2(0)
+ assert self.posix.get_inheritable(fd1) == True
+ assert self.posix.get_inheritable(fd2) == True
+ self.posix.close(fd1)
+ self.posix.close(fd2)
+
+ def test_O_CLOEXEC(self):
+ if not hasattr(self.posix, 'pipe2'):
+ skip("no pipe2")
+ if not hasattr(self.posix, 'O_CLOEXEC'):
+ skip("no O_CLOEXEC")
+ fd1, fd2 = self.posix.pipe2(self.posix.O_CLOEXEC)
+ assert self.posix.get_inheritable(fd1) == False
+ assert self.posix.get_inheritable(fd2) == False
+ self.posix.close(fd1)
+ self.posix.close(fd2)
+
def test_urandom(self):
os = self.posix
s = os.urandom(5)
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1113,37 +1113,74 @@
c_open_osfhandle = external('_open_osfhandle', [rffi.INTPTR_T,
rffi.INT],
rffi.INT)
+ HAVE_PIPE2 = False
+ O_CLOEXEC = None
else:
INT_ARRAY_P = rffi.CArrayPtr(rffi.INT)
c_pipe = external('pipe', [INT_ARRAY_P], rffi.INT,
save_err=rffi.RFFI_SAVE_ERRNO)
+ class CConfig:
+ _compilation_info_ = eci
+ HAVE_PIPE2 = rffi_platform.Has('pipe2')
+ O_CLOEXEC = rffi_platform.DefinedConstantInteger('O_CLOEXEC')
+ config = rffi_platform.configure(CConfig)
+ HAVE_PIPE2 = config['HAVE_PIPE2']
+ O_CLOEXEC = config['O_CLOEXEC']
+ if HAVE_PIPE2:
+ c_pipe2 = external('pipe2', [INT_ARRAY_P, rffi.INT], rffi.INT,
+ save_err=rffi.RFFI_SAVE_ERRNO)
@replace_os_function('pipe')
-def pipe():
+def pipe(flags=0):
+ # 'flags' might be ignored. Check the result.
if _WIN32:
+ # 'flags' ignored
pread = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
try:
- if not CreatePipe(
- pread, pwrite, lltype.nullptr(rffi.VOIDP.TO), 0):
- raise WindowsError(rwin32.GetLastError_saved(),
- "CreatePipe failed")
+ ok = CreatePipe(
+ pread, pwrite, lltype.nullptr(rffi.VOIDP.TO), 0)
hread = rffi.cast(rffi.INTPTR_T, pread[0])
hwrite = rffi.cast(rffi.INTPTR_T, pwrite[0])
finally:
lltype.free(pwrite, flavor='raw')
lltype.free(pread, flavor='raw')
- fdread = c_open_osfhandle(hread, 0)
- fdwrite = c_open_osfhandle(hwrite, 1)
+ if ok:
+ fdread = c_open_osfhandle(hread, 0)
+ fdwrite = c_open_osfhandle(hwrite, 1)
+ if fdread == -1 or fdwrite == -1:
+ rwin32.CloseHandle(hread)
+ rwin32.CloseHandle(hwrite)
+ ok = 0
+ if not ok:
+ raise WindowsError(rwin32.GetLastError_saved(),
+ "CreatePipe failed")
return (fdread, fdwrite)
else:
filedes = lltype.malloc(INT_ARRAY_P.TO, 2, flavor='raw')
try:
- handle_posix_error('pipe', c_pipe(filedes))
+ if HAVE_PIPE2:
+ res = c_pipe2(filedes, flags)
+ if widen(res) != 0 and get_saved_errno() == errno.ENOSYS:
+ res = c_pipe(filedes)
+ else:
+ res = c_pipe(filedes) # 'flags' ignored
+ handle_posix_error('pipe', res)
return (widen(filedes[0]), widen(filedes[1]))
finally:
lltype.free(filedes, flavor='raw')
+def pipe2(flags):
+ # Only available if there is really a c_pipe2 function.
+ # No fallback to pipe() if we get ENOSYS.
+ filedes = lltype.malloc(INT_ARRAY_P.TO, 2, flavor='raw')
+ try:
+ res = c_pipe2(filedes, flags)
+ handle_posix_error('pipe2', res)
+ return (widen(filedes[0]), widen(filedes[1]))
+ finally:
+ lltype.free(filedes, flavor='raw')
+
c_link = external('link', [rffi.CCHARP, rffi.CCHARP], rffi.INT,
save_err=rffi.RFFI_SAVE_ERRNO,)
c_symlink = external('symlink', [rffi.CCHARP, rffi.CCHARP], rffi.INT,
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit