mirror of
https://github.com/python/cpython.git
synced 2025-09-10 02:36:56 +00:00
Issue #22117: The socket module uses _PyTime_t timestamp for timeouts
This commit is contained in:
parent
95e9cef6f0
commit
71694d5c8c
2 changed files with 123 additions and 90 deletions
|
@ -460,7 +460,7 @@ static PyTypeObject sock_type;
|
||||||
#else
|
#else
|
||||||
/* If there's no timeout left, we don't have to call select, so it's a safe,
|
/* If there's no timeout left, we don't have to call select, so it's a safe,
|
||||||
* little white lie. */
|
* little white lie. */
|
||||||
#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0.0)
|
#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
@ -597,9 +597,17 @@ internal_setblocking(PySocketSockObject *s, int block)
|
||||||
after they've reacquired the interpreter lock.
|
after they've reacquired the interpreter lock.
|
||||||
Returns 1 on timeout, -1 on error, 0 otherwise. */
|
Returns 1 on timeout, -1 on error, 0 otherwise. */
|
||||||
static int
|
static int
|
||||||
internal_select_ex(PySocketSockObject *s, int writing, double interval)
|
internal_select_ex(PySocketSockObject *s, int writing, _PyTime_t interval)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
struct pollfd pollfd;
|
||||||
|
_PyTime_t timeout;
|
||||||
|
int timeout_int;
|
||||||
|
#else
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tv;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
/* must be called with the GIL held */
|
/* must be called with the GIL held */
|
||||||
|
@ -607,7 +615,7 @@ internal_select_ex(PySocketSockObject *s, int writing, double interval)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Nothing to do unless we're in timeout mode (not non-blocking) */
|
/* Nothing to do unless we're in timeout mode (not non-blocking) */
|
||||||
if (s->sock_timeout <= 0.0)
|
if (s->sock_timeout <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Guard against closed socket */
|
/* Guard against closed socket */
|
||||||
|
@ -615,46 +623,40 @@ internal_select_ex(PySocketSockObject *s, int writing, double interval)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Handling this condition here simplifies the select loops */
|
/* Handling this condition here simplifies the select loops */
|
||||||
if (interval < 0.0)
|
if (interval < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Prefer poll, if available, since you can poll() any fd
|
/* Prefer poll, if available, since you can poll() any fd
|
||||||
* which can't be done with select(). */
|
* which can't be done with select(). */
|
||||||
#ifdef HAVE_POLL
|
#ifdef HAVE_POLL
|
||||||
{
|
pollfd.fd = s->sock_fd;
|
||||||
struct pollfd pollfd;
|
pollfd.events = writing ? POLLOUT : POLLIN;
|
||||||
int timeout;
|
|
||||||
|
|
||||||
pollfd.fd = s->sock_fd;
|
/* s->sock_timeout is in seconds, timeout in ms */
|
||||||
pollfd.events = writing ? POLLOUT : POLLIN;
|
timeout = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_UP);
|
||||||
|
assert(timeout <= INT_MAX);
|
||||||
|
timeout_int = (int)timeout;
|
||||||
|
|
||||||
/* s->sock_timeout is in seconds, timeout in ms */
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
timeout = (int)(interval * 1000 + 0.5);
|
n = poll(&pollfd, 1, timeout_int);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
|
||||||
n = poll(&pollfd, 1, timeout);
|
|
||||||
Py_END_ALLOW_THREADS;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
{
|
/* conversion was already checked for overflow when
|
||||||
/* Construct the arguments to select */
|
the timeout was set */
|
||||||
fd_set fds;
|
(void)_PyTime_AsTimeval(interval, &tv, _PyTime_ROUND_UP);
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = (int)interval;
|
|
||||||
tv.tv_usec = (int)((interval - tv.tv_sec) * 1e6);
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
FD_SET(s->sock_fd, &fds);
|
|
||||||
|
|
||||||
/* See if the socket is ready */
|
FD_ZERO(&fds);
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
FD_SET(s->sock_fd, &fds);
|
||||||
if (writing)
|
|
||||||
n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
|
/* See if the socket is ready */
|
||||||
NULL, &fds, NULL, &tv);
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
else
|
if (writing)
|
||||||
n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
|
n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
|
||||||
&fds, NULL, NULL, &tv);
|
NULL, &fds, NULL, &tv);
|
||||||
Py_END_ALLOW_THREADS;
|
else
|
||||||
}
|
n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
|
||||||
|
&fds, NULL, NULL, &tv);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
@ -694,14 +696,11 @@ internal_select(PySocketSockObject *s, int writing)
|
||||||
|
|
||||||
#define BEGIN_SELECT_LOOP(s) \
|
#define BEGIN_SELECT_LOOP(s) \
|
||||||
{ \
|
{ \
|
||||||
_PyTime_timeval now, deadline = {0, 0}; \
|
_PyTime_t deadline = 0; \
|
||||||
double interval = s->sock_timeout; \
|
_PyTime_t interval = s->sock_timeout; \
|
||||||
int has_timeout = s->sock_timeout > 0.0; \
|
int has_timeout = (s->sock_timeout > 0); \
|
||||||
if (has_timeout) { \
|
if (has_timeout) \
|
||||||
_PyTime_monotonic(&now); \
|
deadline = _PyTime_GetMonotonicClock() + interval; \
|
||||||
deadline = now; \
|
|
||||||
_PyTime_AddDouble(&deadline, s->sock_timeout, _PyTime_ROUND_UP); \
|
|
||||||
} \
|
|
||||||
while (1) { \
|
while (1) { \
|
||||||
errno = 0; \
|
errno = 0; \
|
||||||
|
|
||||||
|
@ -709,14 +708,13 @@ internal_select(PySocketSockObject *s, int writing)
|
||||||
if (!has_timeout || \
|
if (!has_timeout || \
|
||||||
(!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \
|
(!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \
|
||||||
break; \
|
break; \
|
||||||
_PyTime_monotonic(&now); \
|
interval = deadline - _PyTime_GetMonotonicClock(); \
|
||||||
interval = _PyTime_INTERVAL(now, deadline); \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
/* Initialize a new socket object. */
|
/* Initialize a new socket object. */
|
||||||
|
|
||||||
static double defaulttimeout = -1.0; /* Default timeout for new sockets */
|
static _PyTime_t defaulttimeout = -1; /* Default timeout for new sockets */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_sockobject(PySocketSockObject *s,
|
init_sockobject(PySocketSockObject *s,
|
||||||
|
@ -730,12 +728,12 @@ init_sockobject(PySocketSockObject *s,
|
||||||
s->errorhandler = &set_error;
|
s->errorhandler = &set_error;
|
||||||
#ifdef SOCK_NONBLOCK
|
#ifdef SOCK_NONBLOCK
|
||||||
if (type & SOCK_NONBLOCK)
|
if (type & SOCK_NONBLOCK)
|
||||||
s->sock_timeout = 0.0;
|
s->sock_timeout = 0;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
s->sock_timeout = defaulttimeout;
|
s->sock_timeout = defaulttimeout;
|
||||||
if (defaulttimeout >= 0.0)
|
if (defaulttimeout >= 0)
|
||||||
internal_setblocking(s, 0);
|
internal_setblocking(s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2168,7 +2166,7 @@ sock_setblocking(PySocketSockObject *s, PyObject *arg)
|
||||||
if (block == -1 && PyErr_Occurred())
|
if (block == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
s->sock_timeout = block ? -1.0 : 0.0;
|
s->sock_timeout = block ? -1 : 0;
|
||||||
internal_setblocking(s, block);
|
internal_setblocking(s, block);
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -2182,6 +2180,43 @@ Set the socket to blocking (flag is true) or non-blocking (false).\n\
|
||||||
setblocking(True) is equivalent to settimeout(None);\n\
|
setblocking(True) is equivalent to settimeout(None);\n\
|
||||||
setblocking(False) is equivalent to settimeout(0.0).");
|
setblocking(False) is equivalent to settimeout(0.0).");
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_parse_timeout(_PyTime_t *timeout, PyObject *timeout_obj)
|
||||||
|
{
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
struct timeval tv;
|
||||||
|
#endif
|
||||||
|
int overflow = 0;
|
||||||
|
|
||||||
|
if (timeout_obj == Py_None) {
|
||||||
|
*timeout = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PyTime_FromSecondsObject(timeout, timeout_obj, _PyTime_ROUND_UP) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (*timeout < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Timeout value out of range");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
overflow = (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_UP) < 0);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_POLL
|
||||||
|
timeout = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_UP);
|
||||||
|
overflow = (timeout > INT_MAX);
|
||||||
|
#endif
|
||||||
|
if (overflow) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"timeout doesn't fit into C timeval");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* s.settimeout(timeout) method. Argument:
|
/* s.settimeout(timeout) method. Argument:
|
||||||
None -- no timeout, blocking mode; same as setblocking(True)
|
None -- no timeout, blocking mode; same as setblocking(True)
|
||||||
0.0 -- non-blocking mode; same as setblocking(False)
|
0.0 -- non-blocking mode; same as setblocking(False)
|
||||||
|
@ -2191,22 +2226,13 @@ setblocking(False) is equivalent to settimeout(0.0).");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sock_settimeout(PySocketSockObject *s, PyObject *arg)
|
sock_settimeout(PySocketSockObject *s, PyObject *arg)
|
||||||
{
|
{
|
||||||
double timeout;
|
_PyTime_t timeout;
|
||||||
|
|
||||||
if (arg == Py_None)
|
if (socket_parse_timeout(&timeout, arg) < 0)
|
||||||
timeout = -1.0;
|
return NULL;
|
||||||
else {
|
|
||||||
timeout = PyFloat_AsDouble(arg);
|
|
||||||
if (timeout < 0.0) {
|
|
||||||
if (!PyErr_Occurred())
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"Timeout value out of range");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s->sock_timeout = timeout;
|
s->sock_timeout = timeout;
|
||||||
internal_setblocking(s, timeout < 0.0);
|
internal_setblocking(s, timeout < 0);
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
@ -2225,12 +2251,14 @@ Setting a timeout of zero is the same as setblocking(0).");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sock_gettimeout(PySocketSockObject *s)
|
sock_gettimeout(PySocketSockObject *s)
|
||||||
{
|
{
|
||||||
if (s->sock_timeout < 0.0) {
|
if (s->sock_timeout < 0) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
return PyFloat_FromDouble(s->sock_timeout);
|
double seconds = _PyTime_AsSecondsDouble(s->sock_timeout);
|
||||||
|
return PyFloat_FromDouble(seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(gettimeout_doc,
|
PyDoc_STRVAR(gettimeout_doc,
|
||||||
|
@ -2409,27 +2437,28 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
|
||||||
{
|
{
|
||||||
int res, timeout;
|
int res, timeout;
|
||||||
|
|
||||||
|
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
res = connect(s->sock_fd, addr, addrlen);
|
res = connect(s->sock_fd, addr, addrlen);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
|
||||||
if (s->sock_timeout > 0.0
|
if (s->sock_timeout > 0
|
||||||
&& res < 0 && WSAGetLastError() == WSAEWOULDBLOCK
|
&& res < 0 && WSAGetLastError() == WSAEWOULDBLOCK
|
||||||
&& IS_SELECTABLE(s)) {
|
&& IS_SELECTABLE(s)) {
|
||||||
/* This is a mess. Best solution: trust select */
|
/* This is a mess. Best solution: trust select */
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
fd_set fds_exc;
|
fd_set fds_exc;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
int conv;
|
||||||
|
|
||||||
|
/* conversion was already checked for overflow when
|
||||||
|
the timeout was set */
|
||||||
|
(void)_PyTime_AsTimeval(s->sock_timeout, &tv, _PyTime_ROUND_UP);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
tv.tv_sec = (int)s->sock_timeout;
|
|
||||||
tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(s->sock_fd, &fds);
|
FD_SET(s->sock_fd, &fds);
|
||||||
FD_ZERO(&fds_exc);
|
FD_ZERO(&fds_exc);
|
||||||
|
@ -2469,7 +2498,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (s->sock_timeout > 0.0
|
if (s->sock_timeout > 0
|
||||||
&& res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
|
&& res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
|
||||||
|
|
||||||
timeout = internal_select(s, 1);
|
timeout = internal_select(s, 1);
|
||||||
|
@ -2498,6 +2527,7 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
|
||||||
#endif
|
#endif
|
||||||
*timeoutp = timeout;
|
*timeoutp = timeout;
|
||||||
|
|
||||||
|
assert(res >= 0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2520,8 +2550,11 @@ sock_connect(PySocketSockObject *s, PyObject *addro)
|
||||||
PyErr_SetString(socket_timeout, "timed out");
|
PyErr_SetString(socket_timeout, "timed out");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (res != 0)
|
if (res < 0)
|
||||||
|
return NULL;
|
||||||
|
if (res != 0) {
|
||||||
return s->errorhandler();
|
return s->errorhandler();
|
||||||
|
}
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
@ -2548,6 +2581,9 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro)
|
||||||
|
|
||||||
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
|
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Signals are not errors (though they may raise exceptions). Adapted
|
/* Signals are not errors (though they may raise exceptions). Adapted
|
||||||
from PyErr_SetFromErrnoWithFilenameObject(). */
|
from PyErr_SetFromErrnoWithFilenameObject(). */
|
||||||
if (res == EINTR && PyErr_CheckSignals())
|
if (res == EINTR && PyErr_CheckSignals())
|
||||||
|
@ -3967,10 +4003,14 @@ static PyMemberDef sock_memberlist[] = {
|
||||||
{"family", T_INT, offsetof(PySocketSockObject, sock_family), READONLY, "the socket family"},
|
{"family", T_INT, offsetof(PySocketSockObject, sock_family), READONLY, "the socket family"},
|
||||||
{"type", T_INT, offsetof(PySocketSockObject, sock_type), READONLY, "the socket type"},
|
{"type", T_INT, offsetof(PySocketSockObject, sock_type), READONLY, "the socket type"},
|
||||||
{"proto", T_INT, offsetof(PySocketSockObject, sock_proto), READONLY, "the socket protocol"},
|
{"proto", T_INT, offsetof(PySocketSockObject, sock_proto), READONLY, "the socket protocol"},
|
||||||
{"timeout", T_DOUBLE, offsetof(PySocketSockObject, sock_timeout), READONLY, "the socket timeout"},
|
|
||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef sock_getsetlist[] = {
|
||||||
|
{"timeout", (getter)sock_gettimeout, NULL, PyDoc_STR("the socket timeout")},
|
||||||
|
{NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
/* Deallocate a socket object in response to the last Py_DECREF().
|
/* Deallocate a socket object in response to the last Py_DECREF().
|
||||||
First close the file description. */
|
First close the file description. */
|
||||||
|
|
||||||
|
@ -4034,7 +4074,7 @@ sock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
new = type->tp_alloc(type, 0);
|
new = type->tp_alloc(type, 0);
|
||||||
if (new != NULL) {
|
if (new != NULL) {
|
||||||
((PySocketSockObject *)new)->sock_fd = -1;
|
((PySocketSockObject *)new)->sock_fd = -1;
|
||||||
((PySocketSockObject *)new)->sock_timeout = -1.0;
|
((PySocketSockObject *)new)->sock_timeout = -1;
|
||||||
((PySocketSockObject *)new)->errorhandler = &set_error;
|
((PySocketSockObject *)new)->errorhandler = &set_error;
|
||||||
}
|
}
|
||||||
return new;
|
return new;
|
||||||
|
@ -4217,7 +4257,7 @@ static PyTypeObject sock_type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
sock_methods, /* tp_methods */
|
sock_methods, /* tp_methods */
|
||||||
sock_memberlist, /* tp_members */
|
sock_memberlist, /* tp_members */
|
||||||
0, /* tp_getset */
|
sock_getsetlist, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
|
@ -5540,12 +5580,14 @@ Get host and port for a sockaddr.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
socket_getdefaulttimeout(PyObject *self)
|
socket_getdefaulttimeout(PyObject *self)
|
||||||
{
|
{
|
||||||
if (defaulttimeout < 0.0) {
|
if (defaulttimeout < 0) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
return PyFloat_FromDouble(defaulttimeout);
|
double seconds = _PyTime_AsSecondsDouble(defaulttimeout);
|
||||||
|
return PyFloat_FromDouble(seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(getdefaulttimeout_doc,
|
PyDoc_STRVAR(getdefaulttimeout_doc,
|
||||||
|
@ -5558,19 +5600,10 @@ When the socket module is first imported, the default is None.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
socket_setdefaulttimeout(PyObject *self, PyObject *arg)
|
socket_setdefaulttimeout(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
double timeout;
|
_PyTime_t timeout;
|
||||||
|
|
||||||
if (arg == Py_None)
|
if (socket_parse_timeout(&timeout, arg) < 0)
|
||||||
timeout = -1.0;
|
return NULL;
|
||||||
else {
|
|
||||||
timeout = PyFloat_AsDouble(arg);
|
|
||||||
if (timeout < 0.0) {
|
|
||||||
if (!PyErr_Occurred())
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"Timeout value out of range");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defaulttimeout = timeout;
|
defaulttimeout = timeout;
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ typedef struct {
|
||||||
PyObject *(*errorhandler)(void); /* Error handler; checks
|
PyObject *(*errorhandler)(void); /* Error handler; checks
|
||||||
errno, returns NULL and
|
errno, returns NULL and
|
||||||
sets a Python exception */
|
sets a Python exception */
|
||||||
double sock_timeout; /* Operation timeout in seconds;
|
_PyTime_t sock_timeout; /* Operation timeout in seconds;
|
||||||
0.0 means non-blocking */
|
0.0 means non-blocking */
|
||||||
} PySocketSockObject;
|
} PySocketSockObject;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue