[pypy-commit] pypy py3.5-noninherit: Add rsocket.socketpair(inheritable=..). Fix _socket.socketpair() at
arigo
pypy.commits at gmail.com
Fri Aug 26 11:28:56 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5-noninherit
Changeset: r86572:f44ca4fc29df
Date: 2016-08-26 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/f44ca4fc29df/
Log: Add rsocket.socketpair(inheritable=..). Fix _socket.socketpair() at
app-level.
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -170,7 +170,8 @@
AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
"""
try:
- sock1, sock2 = rsocket.socketpair(family, type, proto)
+ sock1, sock2 = rsocket.socketpair(family, type, proto,
+ inheritable=False)
except SocketError as e:
raise converted_error(space, e)
return space.newtuple([
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -648,6 +648,16 @@
assert len(w) == 1, [str(warning) for warning in w]
assert r in str(w[0])
+ def test_socketpair_non_inheritable(self):
+ import _socket, posix
+ if not hasattr(_socket, 'socketpair'):
+ skip("no socketpair")
+ s1, s2 = _socket.socketpair()
+ assert posix.get_inheritable(s1.fileno()) is False
+ assert posix.get_inheritable(s2.fileno()) is False
+ s1.close()
+ s2.close()
+
class AppTestNetlink:
def setup_class(cls):
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -176,6 +176,7 @@
SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET SOCK_STREAM
+SOCK_CLOEXEC
SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -11,7 +11,7 @@
from rpython.rlib import _rsocket_rffi as _c, jit, rgc
from rpython.rlib.objectmodel import instantiate, keepalive_until_here
from rpython.rlib.rarithmetic import intmask, r_uint
-from rpython.rlib import rthread
+from rpython.rlib import rthread, rposix
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.lltypesystem.rffi import sizeof, offsetof
from rpython.rtyper.extregistry import ExtRegistryEntry
@@ -1032,6 +1032,12 @@
return result
make_socket._annspecialcase_ = 'specialize:arg(4)'
+def sock_set_inheritable(fd, inheritable):
+ try:
+ rposix.set_inheritable(fd, inheritable)
+ except OSError as e:
+ raise CSocketError(e.errno)
+
class SocketError(Exception):
applevelerrcls = 'error'
def __init__(self):
@@ -1090,7 +1096,7 @@
if hasattr(_c, 'socketpair'):
def socketpair(family=socketpair_default_family, type=SOCK_STREAM, proto=0,
- SocketClass=RSocket):
+ SocketClass=RSocket, inheritable=True):
"""socketpair([family[, type[, proto]]]) -> (socket object, socket object)
Create a pair of socket objects from the sockets returned by the platform
@@ -1099,12 +1105,37 @@
AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
"""
result = lltype.malloc(_c.socketpair_t, 2, flavor='raw')
- res = _c.socketpair(family, type, proto, result)
- if res < 0:
- raise last_error()
- fd0 = rffi.cast(lltype.Signed, result[0])
- fd1 = rffi.cast(lltype.Signed, result[1])
- lltype.free(result, flavor='raw')
+ try:
+ res = -1
+ remove_inheritable = not inheritable
+ if not inheritable and SOCK_CLOEXEC is not None:
+ # Non-inheritable: we try to call socketpair() with
+ # SOCK_CLOEXEC, which may fail. If we get EINVAL,
+ # then we fall back to the SOCK_CLOEXEC-less case.
+ res = _c.socketpair(family, type | SOCK_CLOEXEC,
+ proto, result)
+ if res < 0:
+ if _c.geterrno() == errno.EINVAL:
+ # Linux older than 2.6.27 does not support
+ # SOCK_CLOEXEC. An EINVAL might be caused by
+ # random other things, though. Don't cache.
+ pass
+ else:
+ raise last_error()
+ else:
+ remove_inheritable = False
+ #
+ if res < 0:
+ res = _c.socketpair(family, type, proto, result)
+ if res < 0:
+ raise last_error()
+ fd0 = rffi.cast(lltype.Signed, result[0])
+ fd1 = rffi.cast(lltype.Signed, result[1])
+ finally:
+ lltype.free(result, flavor='raw')
+ if remove_inheritable:
+ sock_set_inheritable(fd0, False)
+ sock_set_inheritable(fd1, False)
return (make_socket(fd0, family, type, proto, SocketClass),
make_socket(fd1, family, type, proto, SocketClass))
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -119,6 +119,16 @@
s1.close()
s2.close()
+def test_socketpair_inheritable():
+ if sys.platform == "win32":
+ py.test.skip('No socketpair on Windows')
+ for inh in [False, True]:
+ s1, s2 = socketpair(inheritable=inh)
+ assert rposix.get_inheritable(s1.fd) == inh
+ assert rposix.get_inheritable(s2.fd) == inh
+ s1.close()
+ s2.close()
+
def test_socketpair_recvinto_1():
class Buffer:
def setslice(self, start, string):
More information about the pypy-commit
mailing list