Author: Armin Rigo <[email protected]>
Branch: py3.5-noninherit
Changeset: r86554:1b8d1ba5dcb8
Date: 2016-08-26 15:23 +0200
http://bitbucket.org/pypy/pypy/changeset/1b8d1ba5dcb8/
Log: os.dup(), os.dup2()
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
@@ -536,17 +536,17 @@
"""Create a copy of the file descriptor. Return the new file
descriptor."""
try:
- newfd = os.dup(fd)
+ newfd = rposix.dup(fd, inheritable=False)
except OSError as e:
raise wrap_oserror(space, e)
else:
return space.wrap(newfd)
-@unwrap_spec(old_fd=c_int, new_fd=c_int)
-def dup2(space, old_fd, new_fd):
+@unwrap_spec(old_fd=c_int, new_fd=c_int, inheritable=int)
+def dup2(space, old_fd, new_fd, inheritable=1):
"""Duplicate a file descriptor."""
try:
- os.dup2(old_fd, new_fd)
+ rposix.dup2(old_fd, new_fd, inheritable)
except OSError as e:
raise wrap_oserror(space, e)
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
@@ -106,6 +106,7 @@
posix = self.posix
fd = posix.open(path, posix.O_RDONLY, 0o777)
fd2 = posix.dup(fd)
+ assert posix.get_inheritable(fd2) == False
assert not posix.isatty(fd2)
s = posix.read(fd, 1)
assert s == b't'
@@ -1104,6 +1105,18 @@
self.posix.close(fd1)
self.posix.close(fd2)
+ def test_dup2_inheritable(self):
+ fd1, fd2 = self.posix.pipe()
+ assert self.posix.get_inheritable(fd2) == False
+ self.posix.dup2(fd1, fd2)
+ assert self.posix.get_inheritable(fd2) == True
+ self.posix.dup2(fd1, fd2, False)
+ assert self.posix.get_inheritable(fd2) == False
+ self.posix.dup2(fd1, fd2, True)
+ assert self.posix.get_inheritable(fd2) == True
+ 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
@@ -366,14 +366,22 @@
return result
@replace_os_function('dup')
-def dup(fd):
+def dup(fd, inheritable=True):
validate_fd(fd)
- return handle_posix_error('dup', c_dup(fd))
+ if inheritable:
+ res = c_dup(fd)
+ else:
+ res = c_dup_noninheritable(fd)
+ return handle_posix_error('dup', res)
@replace_os_function('dup2')
-def dup2(fd, newfd):
+def dup2(fd, newfd, inheritable=True):
validate_fd(fd)
- handle_posix_error('dup2', c_dup2(fd, newfd))
+ if inheritable:
+ res = c_dup2(fd, newfd)
+ else:
+ res = c_dup2_noninheritable(fd, newfd)
+ handle_posix_error('dup2', res)
#___________________________________________________________________
@@ -1114,6 +1122,7 @@
rffi.INT],
rffi.INT)
HAVE_PIPE2 = False
+ HAVE_DUP3 = False
O_CLOEXEC = None
else:
INT_ARRAY_P = rffi.CArrayPtr(rffi.INT)
@@ -1122,9 +1131,11 @@
class CConfig:
_compilation_info_ = eci
HAVE_PIPE2 = rffi_platform.Has('pipe2')
+ HAVE_DUP3 = rffi_platform.Has('dup3')
O_CLOEXEC = rffi_platform.DefinedConstantInteger('O_CLOEXEC')
config = rffi_platform.configure(CConfig)
HAVE_PIPE2 = config['HAVE_PIPE2']
+ HAVE_DUP3 = config['HAVE_DUP3']
O_CLOEXEC = config['O_CLOEXEC']
if HAVE_PIPE2:
c_pipe2 = external('pipe2', [INT_ARRAY_P, rffi.INT], rffi.INT,
@@ -2116,7 +2127,7 @@
eci_inheritable = eci.merge(ExternalCompilationInfo(
- separate_module_sources=["""
+ separate_module_sources=[r"""
#include <errno.h>
RPY_EXTERN
@@ -2164,7 +2175,60 @@
return -1;
return !(flags & FD_CLOEXEC);
}
- """],
+
+RPY_EXTERN
+int rpy_dup_noninheritable(int fd)
+{
+#ifdef _WIN32
+#error NotImplementedError
+#endif
+
+#ifdef F_DUPFD_CLOEXEC
+ return fcntl(fd, F_DUPFD_CLOEXEC, 0);
+#else
+ fd = dup(fd);
+ if (fd >= 0) {
+ if (rpy_set_inheritable(fd, 0) != 0) {
+ close(fd);
+ return -1;
+ }
+ }
+ return fd;
+#endif
+}
+
+RPY_EXTERN
+int rpy_dup2_noninheritable(int fd, int fd2)
+{
+#ifdef _WIN32
+#error NotImplementedError
+#endif
+
+#ifdef F_DUP2FD_CLOEXEC
+ return fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
+
+#else
+# if %(HAVE_DUP3)d /* HAVE_DUP3 */
+ static int dup3_works = -1;
+ if (dup3_works != 0) {
+ if (dup3(fd, fd2, O_CLOEXEC) >= 0)
+ return 0;
+ if (dup3_works == -1)
+ dup3_works = (errno != ENOSYS);
+ if (dup3_works)
+ return -1;
+ }
+# endif
+ if (dup2(fd, fd2) < 0)
+ return -1;
+ if (rpy_set_inheritable(fd2, 0) != 0) {
+ close(fd2);
+ return -1;
+ }
+ return 0;
+#endif
+}
+ """ % {'HAVE_DUP3': HAVE_DUP3}],
post_include_bits=['RPY_EXTERN int rpy_set_inheritable(int, int);']))
c_set_inheritable = external('rpy_set_inheritable', [rffi.INT, rffi.INT],
@@ -2173,6 +2237,12 @@
c_get_inheritable = external('rpy_get_inheritable', [rffi.INT],
rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
compilation_info=eci_inheritable)
+c_dup_noninheritable = external('rpy_dup_noninheritable', [rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
+c_dup2_noninheritable = external('rpy_dup2_noninheritable',
[rffi.INT,rffi.INT],
+ rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
+ compilation_info=eci_inheritable)
def set_inheritable(fd, inheritable):
result = c_set_inheritable(fd, inheritable)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit