Commit b8bb5eed authored by Alexey Borzenkov's avatar Alexey Borzenkov

Port gevent vfd to win64

Since long on win64 is 32-bit it cannot hold all possible
SOCKET handle values, making it theoretically possible to
get an exception "OverflowError: Python int too large to
convert to C long" if socket handles become too big. Now
on win64 it properly uses PY_LONG_LONG.
parent 3d5c99c1
...@@ -453,8 +453,13 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]: ...@@ -453,8 +453,13 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
CHECK_LOOP3(self) CHECK_LOOP3(self)
return libev.ev_pending_count(self._ptr) return libev.ev_pending_count(self._ptr)
#ifdef _WIN32
def io(self, libev.vfd_socket_t fd, int events, ref=True, priority=None):
return io(self, fd, events, ref, priority)
#else
def io(self, int fd, int events, ref=True, priority=None): def io(self, int fd, int events, ref=True, priority=None):
return io(self, fd, events, ref, priority) return io(self, fd, events, ref, priority)
#endif
def timer(self, double after, double repeat=0.0, ref=True, priority=None): def timer(self, double after, double repeat=0.0, ref=True, priority=None):
return timer(self, after, repeat, ref, priority) return timer(self, after, repeat, ref, priority)
...@@ -785,7 +790,7 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]: ...@@ -785,7 +790,7 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]:
#ifdef _WIN32 #ifdef _WIN32
def __init__(self, loop loop, long fd, int events, ref=True, priority=None): def __init__(self, loop loop, libev.vfd_socket_t fd, int events, ref=True, priority=None):
if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE): if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE):
raise ValueError('illegal event mask: %r' % events) raise ValueError('illegal event mask: %r' % events)
cdef int vfd = libev.vfd_open(fd) cdef int vfd = libev.vfd_open(fd)
......
cdef extern from "libev_vfd.h": cdef extern from "libev_vfd.h":
#ifdef _WIN32
#ifdef _WIN64
ctypedef long long vfd_socket_t
#else
ctypedef long vfd_socket_t
#endif
#else
ctypedef int vfd_socket_t
#endif
long vfd_get(int) long vfd_get(int)
int vfd_open(long) except -1 int vfd_open(long) except -1
void vfd_free(int) void vfd_free(int)
......
#ifdef _WIN32 #ifdef _WIN32
#ifdef _WIN64
typedef PY_LONG_LONG vfd_socket_t;
#define vfd_socket_object PyLong_FromLongLong
#else
typedef long vfd_socket_t;
#define vfd_socket_object PyInt_FromLong
#endif
#ifdef LIBEV_EMBED #ifdef LIBEV_EMBED
/* /*
* If libev on win32 is embedded, then we can use an * If libev on win32 is embedded, then we can use an
...@@ -13,7 +20,7 @@ ...@@ -13,7 +20,7 @@
typedef struct vfd_entry_t typedef struct vfd_entry_t
{ {
long handle; /* OS handle, i.e. SOCKET */ vfd_socket_t handle; /* OS handle, i.e. SOCKET */
int count; /* Reference count, 0 if free */ int count; /* Reference count, 0 if free */
int next; /* Next free fd, -1 if last */ int next; /* Next free fd, -1 if last */
} vfd_entry; } vfd_entry;
...@@ -58,7 +65,7 @@ static CRITICAL_SECTION* vfd_make_lock() ...@@ -58,7 +65,7 @@ static CRITICAL_SECTION* vfd_make_lock()
* Given a virtual fd returns an OS handle or -1 * Given a virtual fd returns an OS handle or -1
* This function is speed critical, so it cannot use GIL * This function is speed critical, so it cannot use GIL
*/ */
static long vfd_get(int fd) static vfd_socket_t vfd_get(int fd)
{ {
int handle = -1; int handle = -1;
VFD_LOCK_ENTER; VFD_LOCK_ENTER;
...@@ -74,7 +81,7 @@ static long vfd_get(int fd) ...@@ -74,7 +81,7 @@ static long vfd_get(int fd)
* Given an OS handle finds or allocates a virtual fd * Given an OS handle finds or allocates a virtual fd
* Returns -1 on failure and sets Python exception if pyexc is non-zero * Returns -1 on failure and sets Python exception if pyexc is non-zero
*/ */
static int vfd_open_(long handle, int pyexc) static int vfd_open_(vfd_socket_t handle, int pyexc)
{ {
VFD_GIL_DECLARE; VFD_GIL_DECLARE;
int fd = -1; int fd = -1;
...@@ -87,7 +94,13 @@ static int vfd_open_(long handle, int pyexc) ...@@ -87,7 +94,13 @@ static int vfd_open_(long handle, int pyexc)
} }
if (ioctlsocket(handle, FIONREAD, &arg) != 0) { if (ioctlsocket(handle, FIONREAD, &arg) != 0) {
if (pyexc) if (pyexc)
PyErr_Format(PyExc_IOError, "%ld is not a socket (files are not supported)", handle); PyErr_Format(PyExc_IOError,
#ifdef _WIN64
"%lld is not a socket (files are not supported)",
#else
"%ld is not a socket (files are not supported)",
#endif
handle);
goto done; goto done;
} }
if (vfd_map == NULL) { if (vfd_map == NULL) {
...@@ -95,7 +108,7 @@ static int vfd_open_(long handle, int pyexc) ...@@ -95,7 +108,7 @@ static int vfd_open_(long handle, int pyexc)
if (vfd_map == NULL) if (vfd_map == NULL)
goto done; goto done;
} }
key = PyLong_FromLong(handle); key = vfd_socket_object(handle);
/* check if it's already in the dict */ /* check if it's already in the dict */
value = PyDict_GetItem(vfd_map, key); value = PyDict_GetItem(vfd_map, key);
if (value != NULL) { if (value != NULL) {
...@@ -168,14 +181,14 @@ static void vfd_free_(int fd, int needclose) ...@@ -168,14 +181,14 @@ static void vfd_free_(int fd, int needclose)
goto done; /* free entry, ignore */ goto done; /* free entry, ignore */
if (!--vfd_entries[fd].count) { if (!--vfd_entries[fd].count) {
/* fd has just been freed */ /* fd has just been freed */
long handle = vfd_entries[fd].handle; vfd_socket_t handle = vfd_entries[fd].handle;
vfd_entries[fd].handle = -1; vfd_entries[fd].handle = -1;
vfd_entries[fd].next = vfd_next; vfd_entries[fd].next = vfd_next;
vfd_next = fd; vfd_next = fd;
if (needclose) if (needclose)
closesocket(handle); closesocket(handle);
/* vfd_map is assumed to be != NULL */ /* vfd_map is assumed to be != NULL */
key = PyLong_FromLong(handle); key = vfd_socket_object(handle);
PyDict_DelItem(vfd_map, key); PyDict_DelItem(vfd_map, key);
Py_DECREF(key); Py_DECREF(key);
} }
...@@ -203,6 +216,7 @@ done: ...@@ -203,6 +216,7 @@ done:
/* /*
* On non-win32 platforms vfd_* are noop macros * On non-win32 platforms vfd_* are noop macros
*/ */
typedef int vfd_socket_t;
#define vfd_get(fd) (fd) #define vfd_get(fd) (fd)
#define vfd_open(fd) ((int)(fd)) #define vfd_open(fd) ((int)(fd))
#define vfd_free(fd) #define vfd_free(fd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment