mirror of
https://github.com/python/cpython.git
synced 2025-11-11 02:52:04 +00:00
#1494314: Fix a regression with high-numbered sockets in 2.4.3. This
means that select() on sockets > FD_SETSIZE (typically 1024) work again. The patch makes sockets use poll() internally where available.
This commit is contained in:
parent
06c68b800c
commit
93ab5fa191
3 changed files with 76 additions and 17 deletions
|
|
@ -105,6 +105,10 @@ Library
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- #1494314: Fix a regression with high-numbered sockets in 2.4.3. This
|
||||||
|
means that select() on sockets > FD_SETSIZE (typically 1024) work again.
|
||||||
|
The patch makes sockets use poll() internally where available.
|
||||||
|
|
||||||
- Assigning None to pointer type fields in ctypes structures possible
|
- Assigning None to pointer type fields in ctypes structures possible
|
||||||
overwrote the wrong fields, this is fixed now.
|
overwrote the wrong fields, this is fixed now.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ enum py_ssl_error {
|
||||||
/* Include symbols from _socket module */
|
/* Include symbols from _socket module */
|
||||||
#include "socketmodule.h"
|
#include "socketmodule.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_POLL_H)
|
||||||
|
#include <poll.h>
|
||||||
|
#elif defined(HAVE_SYS_POLL_H)
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Include OpenSSL header files */
|
/* Include OpenSSL header files */
|
||||||
#include "openssl/rsa.h"
|
#include "openssl/rsa.h"
|
||||||
#include "openssl/crypto.h"
|
#include "openssl/crypto.h"
|
||||||
|
|
@ -351,7 +357,7 @@ static void PySSL_dealloc(PySSLObject *self)
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the socket has a timeout, do a select() on the socket.
|
/* If the socket has a timeout, do a select()/poll() on the socket.
|
||||||
The argument writing indicates the direction.
|
The argument writing indicates the direction.
|
||||||
Returns one of the possibilities in the timeout_state enum (above).
|
Returns one of the possibilities in the timeout_state enum (above).
|
||||||
*/
|
*/
|
||||||
|
|
@ -373,6 +379,26 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
|
||||||
if (s->sock_fd < 0)
|
if (s->sock_fd < 0)
|
||||||
return SOCKET_HAS_BEEN_CLOSED;
|
return SOCKET_HAS_BEEN_CLOSED;
|
||||||
|
|
||||||
|
/* Prefer poll, if available, since you can poll() any fd
|
||||||
|
* which can't be done with select(). */
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
{
|
||||||
|
struct pollfd pollfd;
|
||||||
|
int timeout;
|
||||||
|
|
||||||
|
pollfd.fd = s->sock_fd;
|
||||||
|
pollfd.events = writing ? POLLOUT : POLLIN;
|
||||||
|
|
||||||
|
/* s->sock_timeout is in seconds, timeout in ms */
|
||||||
|
timeout = (int)(s->sock_timeout * 1000 + 0.5);
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
rc = poll(&pollfd, 1, timeout);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
goto normal_return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Guard against socket too large for select*/
|
/* Guard against socket too large for select*/
|
||||||
#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
|
#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
|
||||||
if (s->sock_fd >= FD_SETSIZE)
|
if (s->sock_fd >= FD_SETSIZE)
|
||||||
|
|
@ -393,6 +419,7 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
|
||||||
rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
|
rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
normal_return:
|
||||||
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
|
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
|
||||||
(when we are able to write or when there's something to read) */
|
(when we are able to write or when there's something to read) */
|
||||||
return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK;
|
return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK;
|
||||||
|
|
|
||||||
|
|
@ -411,14 +411,24 @@ static int taskwindow;
|
||||||
there has to be a circular reference. */
|
there has to be a circular reference. */
|
||||||
static PyTypeObject sock_type;
|
static PyTypeObject sock_type;
|
||||||
|
|
||||||
/* Can we call select() with this socket without a buffer overrun? */
|
#if defined(HAVE_POLL_H)
|
||||||
|
#include <poll.h>
|
||||||
|
#elif defined(HAVE_SYS_POLL_H)
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
|
#ifdef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
|
||||||
/* Platform can select file descriptors beyond FD_SETSIZE */
|
/* Platform can select file descriptors beyond FD_SETSIZE */
|
||||||
#define IS_SELECTABLE(s) 1
|
#define IS_SELECTABLE(s) 1
|
||||||
|
#elif defined(HAVE_POLL)
|
||||||
|
/* Instead of select(), we'll use poll() since poll() works on any fd. */
|
||||||
|
#define IS_SELECTABLE(s) 1
|
||||||
|
/* Can we call select() with this socket without a buffer overrun? */
|
||||||
#else
|
#else
|
||||||
/* POSIX says selecting file descriptors beyond FD_SETSIZE
|
/* POSIX says selecting file descriptors beyond FD_SETSIZE
|
||||||
has undefined behaviour. */
|
has undefined behaviour. If there's no timeout left, we don't have to
|
||||||
#define IS_SELECTABLE(s) ((s)->sock_fd < FD_SETSIZE)
|
call select, so it's a safe, little white lie. */
|
||||||
|
#define IS_SELECTABLE(s) ((s)->sock_fd < FD_SETSIZE || s->sock_timeout <= 0.0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
|
@ -686,7 +696,7 @@ internal_setblocking(PySocketSockObject *s, int block)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do a select() on the socket, if necessary (sock_timeout > 0).
|
/* Do a select()/poll() on the socket, if necessary (sock_timeout > 0).
|
||||||
The argument writing indicates the direction.
|
The argument writing indicates the direction.
|
||||||
This does not raise an exception; we'll let our caller do that
|
This does not raise an exception; we'll let our caller do that
|
||||||
after they've reacquired the interpreter lock.
|
after they've reacquired the interpreter lock.
|
||||||
|
|
@ -694,8 +704,6 @@ internal_setblocking(PySocketSockObject *s, int block)
|
||||||
static int
|
static int
|
||||||
internal_select(PySocketSockObject *s, int writing)
|
internal_select(PySocketSockObject *s, int writing)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
|
||||||
struct timeval tv;
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* Nothing to do unless we're in timeout mode (not non-blocking) */
|
/* Nothing to do unless we're in timeout mode (not non-blocking) */
|
||||||
|
|
@ -706,7 +714,25 @@ internal_select(PySocketSockObject *s, int writing)
|
||||||
if (s->sock_fd < 0)
|
if (s->sock_fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Prefer poll, if available, since you can poll() any fd
|
||||||
|
* which can't be done with select(). */
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
{
|
||||||
|
struct pollfd pollfd;
|
||||||
|
int timeout;
|
||||||
|
|
||||||
|
pollfd.fd = s->sock_fd;
|
||||||
|
pollfd.events = writing ? POLLOUT : POLLIN;
|
||||||
|
|
||||||
|
/* s->sock_timeout is in seconds, timeout in ms */
|
||||||
|
timeout = (int)(s->sock_timeout * 1000 + 0.5);
|
||||||
|
n = poll(&pollfd, 1, timeout);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
/* Construct the arguments to select */
|
/* Construct the arguments to select */
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tv;
|
||||||
tv.tv_sec = (int)s->sock_timeout;
|
tv.tv_sec = (int)s->sock_timeout;
|
||||||
tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
|
tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
|
|
@ -717,6 +743,8 @@ internal_select(PySocketSockObject *s, int writing)
|
||||||
n = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
|
n = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
|
||||||
else
|
else
|
||||||
n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
|
n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue