mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
socketfromfd: fix cross platform usage
on osx and maybe some other systems, SO_PROTOCOL is not set, also the socket family is not detected correctly. This patch remove default values in socketfromfd and do the following: * detect proper family using getsockname instead of getsocktopt * if no type is given, default to SOCK_STREAM (we don't have any other type) * if no protocol is given, default to 0 and let the system take care of it.
This commit is contained in:
parent
fa32aa7757
commit
883e62da46
@ -16,10 +16,6 @@ from .util import find_library
|
|||||||
|
|
||||||
__all__ = ('fromfd',)
|
__all__ = ('fromfd',)
|
||||||
|
|
||||||
SO_DOMAIN = getattr(socket, 'SO_DOMAIN', 39)
|
|
||||||
SO_TYPE = getattr(socket, 'SO_TYPE', 3)
|
|
||||||
SO_PROTOCOL = getattr(socket, 'SO_PROTOCOL', 38)
|
|
||||||
|
|
||||||
_libc_name = find_library('c')
|
_libc_name = find_library('c')
|
||||||
if _libc_name is not None:
|
if _libc_name is not None:
|
||||||
if sys.platform.startswith("aix"):
|
if sys.platform.startswith("aix"):
|
||||||
@ -47,8 +43,12 @@ def _errcheck_errno(result, func, arguments):
|
|||||||
|
|
||||||
if platform.system() == 'SunOS':
|
if platform.system() == 'SunOS':
|
||||||
_libc_getsockopt = libc._so_getsockopt
|
_libc_getsockopt = libc._so_getsockopt
|
||||||
|
_libc_getsockname = libc._so_getsockname
|
||||||
else:
|
else:
|
||||||
_libc_getsockopt = libc.getsockopt
|
_libc_getsockopt = libc.getsockopt
|
||||||
|
_libc_getsockname = libc.getsockname
|
||||||
|
|
||||||
|
|
||||||
_libc_getsockopt.argtypes = [
|
_libc_getsockopt.argtypes = [
|
||||||
ctypes.c_int, # int sockfd
|
ctypes.c_int, # int sockfd
|
||||||
ctypes.c_int, # int level
|
ctypes.c_int, # int level
|
||||||
@ -59,6 +59,17 @@ _libc_getsockopt.argtypes = [
|
|||||||
_libc_getsockopt.restype = ctypes.c_int # 0: ok, -1: err
|
_libc_getsockopt.restype = ctypes.c_int # 0: ok, -1: err
|
||||||
_libc_getsockopt.errcheck = _errcheck_errno
|
_libc_getsockopt.errcheck = _errcheck_errno
|
||||||
|
|
||||||
|
class SockAddr(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('sa_len', ctypes.c_uint8),
|
||||||
|
('sa_family', ctypes.c_uint8),
|
||||||
|
('sa_data', ctypes.c_char * 14)
|
||||||
|
]
|
||||||
|
_libc_getsockname.argtypes = [
|
||||||
|
ctypes.c_int,
|
||||||
|
ctypes.POINTER(SockAddr),
|
||||||
|
ctypes.POINTER(ctypes.c_int)
|
||||||
|
]
|
||||||
|
|
||||||
def _raw_getsockopt(fd, level, optname):
|
def _raw_getsockopt(fd, level, optname):
|
||||||
"""Make raw getsockopt() call for int32 optval
|
"""Make raw getsockopt() call for int32 optval
|
||||||
@ -74,6 +85,11 @@ def _raw_getsockopt(fd, level, optname):
|
|||||||
ctypes.byref(optval), ctypes.byref(optlen))
|
ctypes.byref(optval), ctypes.byref(optlen))
|
||||||
return optval.value
|
return optval.value
|
||||||
|
|
||||||
|
def _raw_getsockname(fd):
|
||||||
|
sockaddr = SockAddr()
|
||||||
|
len = ctypes.c_int(ctypes.sizeof(sockaddr))
|
||||||
|
_libc_getsockname(fd, sockaddr, len)
|
||||||
|
return sockaddr.sa_family
|
||||||
|
|
||||||
def fromfd(fd, keep_fd=True):
|
def fromfd(fd, keep_fd=True):
|
||||||
"""Create a socket from a file descriptor
|
"""Create a socket from a file descriptor
|
||||||
@ -92,10 +108,15 @@ def fromfd(fd, keep_fd=True):
|
|||||||
:return: socket.socket instance
|
:return: socket.socket instance
|
||||||
:raises OSError: for invalid socket fd
|
:raises OSError: for invalid socket fd
|
||||||
"""
|
"""
|
||||||
family = _raw_getsockopt(fd, socket.SOL_SOCKET, SO_DOMAIN)
|
family = _raw_getsockname(fd)
|
||||||
typ = _raw_getsockopt(fd, socket.SOL_SOCKET, SO_TYPE)
|
if hasattr(socket, 'SO_TYPE'):
|
||||||
proto = _raw_getsockopt(fd, socket.SOL_SOCKET, SO_PROTOCOL)
|
typ = _raw_getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_TYPE'))
|
||||||
s
|
else:
|
||||||
|
typ = socket.SOCK_STREAM
|
||||||
|
if hasattr(socket, 'SO_PROTOCOL'):
|
||||||
|
proto = _raw_getsockopt(fd, socket.SOL_SOCKET, getattr(socket, 'SO_PROTOCOL'))
|
||||||
|
else:
|
||||||
|
proto = 0
|
||||||
if keep_fd:
|
if keep_fd:
|
||||||
return socket.fromfd(fd, family, typ, proto)
|
return socket.fromfd(fd, family, typ, proto)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user