track embedded python distribution

This commit is contained in:
James Taylor
2018-07-12 23:40:30 -07:00
parent fe9fe82577
commit c3b9f8c458
80 changed files with 81288 additions and 6 deletions

View File

View File

@@ -0,0 +1,75 @@
# pylint: disable=no-member
# This module is only used to create and compile the gevent._corecffi module;
# nothing should be directly imported from it except `ffi`, which should only be
# used for `ffi.compile()`; programs should import gevent._corecfffi.
# However, because we are using "out-of-line" mode, it is necessary to examine
# this file to know what functions are created and available on the generated
# module.
from __future__ import absolute_import, print_function
import sys
import os
import os.path # pylint:disable=no-name-in-module
import struct
__all__ = []
def system_bits():
return struct.calcsize('P') * 8
def st_nlink_type():
if sys.platform == "darwin" or sys.platform.startswith("freebsd"):
return "short"
if system_bits() == 32:
return "unsigned long"
return "long long"
from cffi import FFI
ffi = FFI()
thisdir = os.path.dirname(os.path.abspath(__file__))
def read_source(name):
with open(os.path.join(thisdir, name), 'r') as f:
return f.read()
_cdef = read_source('_corecffi_cdef.c')
_source = read_source('_corecffi_source.c')
_cdef = _cdef.replace('#define GEVENT_ST_NLINK_T int', '')
_cdef = _cdef.replace('#define GEVENT_STRUCT_DONE int', '')
_cdef = _cdef.replace('GEVENT_ST_NLINK_T', st_nlink_type())
_cdef = _cdef.replace("GEVENT_STRUCT_DONE _;", '...;')
if sys.platform.startswith('win'):
# We must have the vfd_open, etc, functions on
# Windows. But on other platforms, going through
# CFFI to just return the file-descriptor is slower
# than just doing it in Python, so we check for and
# workaround their absence in corecffi.py
_cdef += """
typedef int... vfd_socket_t;
int vfd_open(vfd_socket_t);
vfd_socket_t vfd_get(int);
void vfd_free(int);
"""
include_dirs = [
thisdir, # libev_vfd.h
os.path.abspath(os.path.join(thisdir, '..', '..', '..', 'deps', 'libev')),
]
ffi.cdef(_cdef)
ffi.set_source('gevent.libev._corecffi', _source, include_dirs=include_dirs)
if __name__ == '__main__':
# XXX: Note, on Windows, we would need to specify the external libraries
# that should be linked in, such as ws2_32 and (because libev_vfd.h makes
# Python.h calls) the proper Python library---at least for PyPy. I never got
# that to work though, and calling python functions is strongly discouraged
# from CFFI code.
ffi.compile()

View File

@@ -0,0 +1,226 @@
/* libev interface */
#define EV_MINPRI ...
#define EV_MAXPRI ...
#define EV_VERSION_MAJOR ...
#define EV_VERSION_MINOR ...
#define EV_UNDEF ...
#define EV_NONE ...
#define EV_READ ...
#define EV_WRITE ...
#define EV__IOFDSET ...
#define EV_TIMER ...
#define EV_PERIODIC ...
#define EV_SIGNAL ...
#define EV_CHILD ...
#define EV_STAT ...
#define EV_IDLE ...
#define EV_PREPARE ...
#define EV_CHECK ...
#define EV_EMBED ...
#define EV_FORK ...
#define EV_CLEANUP ...
#define EV_ASYNC ...
#define EV_CUSTOM ...
#define EV_ERROR ...
#define EVFLAG_AUTO ...
#define EVFLAG_NOENV ...
#define EVFLAG_FORKCHECK ...
#define EVFLAG_NOINOTIFY ...
#define EVFLAG_SIGNALFD ...
#define EVFLAG_NOSIGMASK ...
#define EVBACKEND_SELECT ...
#define EVBACKEND_POLL ...
#define EVBACKEND_EPOLL ...
#define EVBACKEND_KQUEUE ...
#define EVBACKEND_DEVPOLL ...
#define EVBACKEND_PORT ...
/* #define EVBACKEND_IOCP ... */
#define EVBACKEND_ALL ...
#define EVBACKEND_MASK ...
#define EVRUN_NOWAIT ...
#define EVRUN_ONCE ...
#define EVBREAK_CANCEL ...
#define EVBREAK_ONE ...
#define EVBREAK_ALL ...
/* markers for the CFFI parser. Replaced when the string is read. */
#define GEVENT_STRUCT_DONE int
#define GEVENT_ST_NLINK_T int
struct ev_loop {
int backend_fd;
int activecnt;
GEVENT_STRUCT_DONE _;
};
// Watcher types
// base for all watchers
struct ev_watcher{
GEVENT_STRUCT_DONE _;
};
struct ev_io {
int fd;
int events;
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_timer {
double at;
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_signal {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_idle {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_prepare {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_check {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_fork {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_async {
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_child {
int pid;
int rpid;
int rstatus;
void* data;
GEVENT_STRUCT_DONE _;
};
struct stat {
GEVENT_ST_NLINK_T st_nlink;
GEVENT_STRUCT_DONE _;
};
struct ev_stat {
struct stat attr;
const char* path;
struct stat prev;
double interval;
void* data;
GEVENT_STRUCT_DONE _;
};
typedef double ev_tstamp;
int ev_version_major();
int ev_version_minor();
unsigned int ev_supported_backends (void);
unsigned int ev_recommended_backends (void);
unsigned int ev_embeddable_backends (void);
ev_tstamp ev_time (void);
void ev_set_syserr_cb(void *);
int ev_priority(void*);
void ev_set_priority(void*, int);
int ev_is_pending(void*);
int ev_is_active(void*);
void ev_io_init(struct ev_io*, void* callback, int fd, int events);
void ev_io_start(struct ev_loop*, struct ev_io*);
void ev_io_stop(struct ev_loop*, struct ev_io*);
void ev_feed_event(struct ev_loop*, void*, int);
void ev_timer_init(struct ev_timer*, void *callback, double, double);
void ev_timer_start(struct ev_loop*, struct ev_timer*);
void ev_timer_stop(struct ev_loop*, struct ev_timer*);
void ev_timer_again(struct ev_loop*, struct ev_timer*);
void ev_signal_init(struct ev_signal*, void* callback, int);
void ev_signal_start(struct ev_loop*, struct ev_signal*);
void ev_signal_stop(struct ev_loop*, struct ev_signal*);
void ev_idle_init(struct ev_idle*, void* callback);
void ev_idle_start(struct ev_loop*, struct ev_idle*);
void ev_idle_stop(struct ev_loop*, struct ev_idle*);
void ev_prepare_init(struct ev_prepare*, void* callback);
void ev_prepare_start(struct ev_loop*, struct ev_prepare*);
void ev_prepare_stop(struct ev_loop*, struct ev_prepare*);
void ev_check_init(struct ev_check*, void* callback);
void ev_check_start(struct ev_loop*, struct ev_check*);
void ev_check_stop(struct ev_loop*, struct ev_check*);
void ev_fork_init(struct ev_fork*, void* callback);
void ev_fork_start(struct ev_loop*, struct ev_fork*);
void ev_fork_stop(struct ev_loop*, struct ev_fork*);
void ev_async_init(struct ev_async*, void* callback);
void ev_async_start(struct ev_loop*, struct ev_async*);
void ev_async_stop(struct ev_loop*, struct ev_async*);
void ev_async_send(struct ev_loop*, struct ev_async*);
int ev_async_pending(struct ev_async*);
void ev_child_init(struct ev_child*, void* callback, int, int);
void ev_child_start(struct ev_loop*, struct ev_child*);
void ev_child_stop(struct ev_loop*, struct ev_child*);
void ev_stat_init(struct ev_stat*, void* callback, char*, double);
void ev_stat_start(struct ev_loop*, struct ev_stat*);
void ev_stat_stop(struct ev_loop*, struct ev_stat*);
struct ev_loop *ev_default_loop (unsigned int flags);
struct ev_loop* ev_loop_new(unsigned int flags);
void ev_loop_destroy(struct ev_loop*);
void ev_loop_fork(struct ev_loop*);
int ev_is_default_loop (struct ev_loop *);
unsigned int ev_iteration(struct ev_loop*);
unsigned int ev_depth(struct ev_loop*);
unsigned int ev_backend(struct ev_loop*);
void ev_verify(struct ev_loop*);
void ev_run(struct ev_loop*, int flags);
ev_tstamp ev_now (struct ev_loop *);
void ev_now_update (struct ev_loop *); /* update event loop time */
void ev_ref(struct ev_loop*);
void ev_unref(struct ev_loop*);
void ev_break(struct ev_loop*, int);
unsigned int ev_pending_count(struct ev_loop*);
struct ev_loop* gevent_ev_default_loop(unsigned int flags);
void gevent_install_sigchld_handler();
void gevent_reset_sigchld_handler();
void (*gevent_noop)(struct ev_loop *_loop, struct ev_timer *w, int revents);
void ev_sleep (ev_tstamp delay); /* sleep for a while */
/* gevent callbacks */
static int (*python_callback)(void* handle, int revents);
static void (*python_handle_error)(void* handle, int revents);
static void (*python_stop)(void* handle);
/*
* We use a single C callback for every watcher type, which in turn calls the
* Python callbacks. The ev_watcher pointer type can be used for every watcher type
* because they all start with the same members---libev itself relies on this. Each
* watcher types has a 'void* data' that stores the CFFI handle to the Python watcher
* object.
*/
static void _gevent_generic_callback(struct ev_loop* loop, struct ev_watcher* watcher, int revents);

View File

@@ -0,0 +1,45 @@
// passed to the real C compiler
#define LIBEV_EMBED 1
#ifdef _WIN32
#define EV_STANDALONE 1
#include "libev_vfd.h"
#endif
#include "libev.h"
static void
_gevent_noop(struct ev_loop *_loop, struct ev_timer *w, int revents) { }
void (*gevent_noop)(struct ev_loop *, struct ev_timer *, int) = &_gevent_noop;
static int (*python_callback)(void* handle, int revents);
static void (*python_handle_error)(void* handle, int revents);
static void (*python_stop)(void* handle);
static void _gevent_generic_callback(struct ev_loop* loop,
struct ev_watcher* watcher,
int revents)
{
void* handle = watcher->data;
int cb_result = python_callback(handle, revents);
switch(cb_result) {
case -1:
// in case of exception, call self.loop.handle_error;
// this function is also responsible for stopping the watcher
// and allowing memory to be freed
python_handle_error(handle, revents);
break;
case 0:
// Code to stop the event. Note that if python_callback
// has disposed of the last reference to the handle,
// `watcher` could now be invalid/disposed memory!
if (!ev_is_active(watcher)) {
python_stop(handle);
}
break;
default:
assert(cb_result == 1);
// watcher is already stopped and dead, nothing to do.
}
}

View File

@@ -0,0 +1,225 @@
/* Copyright (c) 2011-2012 Denis Bilenko. See LICENSE for details. */
#ifdef Py_PYTHON_H
/* the name changes depending on our file layout and --module-name option */
#define _GEVENTLOOP struct __pyx_vtabstruct_6gevent_5libev_8corecext_loop
static void gevent_handle_error(struct PyGeventLoopObject* loop, PyObject* context) {
PyThreadState *tstate;
PyObject *type, *value, *traceback, *result;
tstate = PyThreadState_GET();
type = tstate->curexc_type;
if (!type)
return;
value = tstate->curexc_value;
traceback = tstate->curexc_traceback;
if (!value) value = Py_None;
if (!traceback) traceback = Py_None;
Py_INCREF(type);
Py_INCREF(value);
Py_INCREF(traceback);
PyErr_Clear();
result = ((_GEVENTLOOP *)loop->__pyx_vtab)->handle_error(loop, context, type, value, traceback, 0);
if (result) {
Py_DECREF(result);
}
else {
PyErr_Print();
PyErr_Clear();
}
Py_DECREF(type);
Py_DECREF(value);
Py_DECREF(traceback);
}
static CYTHON_INLINE void gevent_check_signals(struct PyGeventLoopObject* loop) {
if (!ev_is_default_loop(loop->_ptr)) {
/* only reporting signals on the default loop */
return;
}
PyErr_CheckSignals();
if (PyErr_Occurred()) gevent_handle_error(loop, Py_None);
}
#define GET_OBJECT(PY_TYPE, EV_PTR, MEMBER) \
((struct PY_TYPE *)(((char *)EV_PTR) - offsetof(struct PY_TYPE, MEMBER)))
#ifdef WITH_THREAD
#define GIL_DECLARE PyGILState_STATE ___save
#define GIL_ENSURE ___save = PyGILState_Ensure();
#define GIL_RELEASE PyGILState_Release(___save);
#else
#define GIL_DECLARE
#define GIL_ENSURE
#define GIL_RELEASE
#endif
static void gevent_stop(PyObject* watcher, struct PyGeventLoopObject* loop) {
PyObject *result, *method;
int error;
error = 1;
method = PyObject_GetAttrString(watcher, "stop");
if (method) {
result = PyObject_Call(method, __pyx_empty_tuple, NULL);
if (result) {
Py_DECREF(result);
error = 0;
}
Py_DECREF(method);
}
if (error) {
gevent_handle_error(loop, watcher);
}
}
static void gevent_callback(struct PyGeventLoopObject* loop, PyObject* callback, PyObject* args, PyObject* watcher, void *c_watcher, int revents) {
GIL_DECLARE;
PyObject *result, *py_events;
long length;
py_events = 0;
GIL_ENSURE;
Py_INCREF(loop);
Py_INCREF(callback);
Py_INCREF(args);
Py_INCREF(watcher);
gevent_check_signals(loop);
if (args == Py_None) {
args = __pyx_empty_tuple;
}
length = PyTuple_Size(args);
if (length < 0) {
gevent_handle_error(loop, watcher);
goto end;
}
if (length > 0 && PyTuple_GET_ITEM(args, 0) == GEVENT_CORE_EVENTS) {
py_events = PyInt_FromLong(revents);
if (!py_events) {
gevent_handle_error(loop, watcher);
goto end;
}
PyTuple_SET_ITEM(args, 0, py_events);
}
else {
py_events = NULL;
}
result = PyObject_Call(callback, args, NULL);
if (result) {
Py_DECREF(result);
}
else {
gevent_handle_error(loop, watcher);
if (revents & (EV_READ|EV_WRITE)) {
/* io watcher: not stopping it may cause the failing callback to be called repeatedly */
gevent_stop(watcher, loop);
goto end;
}
}
if (!ev_is_active(c_watcher)) {
/* Watcher was stopped, maybe by libev. Let's call stop() to clean up
* 'callback' and 'args' properties, do Py_DECREF() and ev_ref() if necessary.
* BTW, we don't need to check for EV_ERROR, because libev stops the watcher in that case. */
gevent_stop(watcher, loop);
}
end:
if (py_events) {
Py_DECREF(py_events);
PyTuple_SET_ITEM(args, 0, GEVENT_CORE_EVENTS);
}
Py_DECREF(watcher);
Py_DECREF(args);
Py_DECREF(callback);
Py_DECREF(loop);
GIL_RELEASE;
}
static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb) {
/* no need for GIL here because it is only called from run_callbacks which already has GIL */
PyObject *result, *callback, *args;
if (!loop || !cb)
return;
callback = cb->callback;
args = cb->args;
if (!callback || !args)
return;
if (callback == Py_None || args == Py_None)
return;
Py_INCREF(loop);
Py_INCREF(callback);
Py_INCREF(args);
Py_INCREF(Py_None);
Py_DECREF(cb->callback);
cb->callback = Py_None;
result = PyObject_Call(callback, args, NULL);
if (result) {
Py_DECREF(result);
}
else {
gevent_handle_error(loop, (PyObject*)cb);
}
Py_INCREF(Py_None);
Py_DECREF(cb->args);
cb->args = Py_None;
Py_DECREF(callback);
Py_DECREF(args);
Py_DECREF(loop);
}
#undef DEFINE_CALLBACK
#define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \
static void gevent_callback_##WATCHER_LC(struct ev_loop *_loop, void *c_watcher, int revents) { \
struct PyGevent##WATCHER_TYPE##Object* watcher = GET_OBJECT(PyGevent##WATCHER_TYPE##Object, c_watcher, _watcher); \
gevent_callback(watcher->loop, watcher->_callback, watcher->args, (PyObject*)watcher, c_watcher, revents); \
}
DEFINE_CALLBACKS
static void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int revents) {
struct PyGeventLoopObject* loop;
PyObject *result;
GIL_DECLARE;
GIL_ENSURE;
loop = GET_OBJECT(PyGeventLoopObject, watcher, _prepare);
Py_INCREF(loop);
gevent_check_signals(loop);
result = ((_GEVENTLOOP *)loop->__pyx_vtab)->_run_callbacks(loop);
if (result) {
Py_DECREF(result);
}
else {
PyErr_Print();
PyErr_Clear();
}
Py_DECREF(loop);
GIL_RELEASE;
}
#if defined(_WIN32)
static void gevent_periodic_signal_check(struct ev_loop *_loop, void *watcher, int revents) {
GIL_DECLARE;
GIL_ENSURE;
gevent_check_signals(GET_OBJECT(PyGeventLoopObject, watcher, _periodic_signal_checker));
GIL_RELEASE;
}
#endif /* _WIN32 */
#endif /* Py_PYTHON_H */

View File

@@ -0,0 +1,43 @@
#define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \
static void gevent_callback_##WATCHER_LC(struct ev_loop *, void *, int);
#define DEFINE_CALLBACKS0 \
DEFINE_CALLBACK(io, IO); \
DEFINE_CALLBACK(timer, Timer); \
DEFINE_CALLBACK(signal, Signal); \
DEFINE_CALLBACK(idle, Idle); \
DEFINE_CALLBACK(prepare, Prepare); \
DEFINE_CALLBACK(check, Check); \
DEFINE_CALLBACK(fork, Fork); \
DEFINE_CALLBACK(async, Async); \
DEFINE_CALLBACK(stat, Stat);
#ifndef _WIN32
#define DEFINE_CALLBACKS \
DEFINE_CALLBACKS0 \
DEFINE_CALLBACK(child, Child)
#else
#define DEFINE_CALLBACKS DEFINE_CALLBACKS0
#endif
DEFINE_CALLBACKS
static void gevent_run_callbacks(struct ev_loop *, void *, int);
struct PyGeventLoopObject;
static void gevent_handle_error(struct PyGeventLoopObject* loop, PyObject* context);
struct PyGeventCallbackObject;
static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb);
#if defined(_WIN32)
static void gevent_periodic_signal_check(struct ev_loop *, void *, int);
#endif
static void gevent_noop(struct ev_loop *_loop, void *watcher, int revents) { }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
#if defined(LIBEV_EMBED)
#include "ev.c"
#else
#include "ev.h"
#ifndef _WIN32
#include <signal.h>
#endif
#endif
#ifndef _WIN32
static struct sigaction libev_sigchld;
/*
* Track the state of whether we have installed
* the libev sigchld handler specifically.
* If it's non-zero, libev_sigchld will be valid and set to the action
* that libev needs to do.
* If it's 1, we need to install libev_sigchld to make libev
* child handlers work (on request).
*/
static int sigchld_state = 0;
static struct ev_loop* gevent_ev_default_loop(unsigned int flags)
{
struct ev_loop* result;
struct sigaction tmp;
if (sigchld_state)
return ev_default_loop(flags);
// Request the old SIGCHLD handler
sigaction(SIGCHLD, NULL, &tmp);
// Get the loop, which will install a SIGCHLD handler
result = ev_default_loop(flags);
// XXX what if SIGCHLD received there?
// Now restore the previous SIGCHLD handler
sigaction(SIGCHLD, &tmp, &libev_sigchld);
sigchld_state = 1;
return result;
}
static void gevent_install_sigchld_handler(void) {
if (sigchld_state == 1) {
sigaction(SIGCHLD, &libev_sigchld, NULL);
sigchld_state = 2;
}
}
static void gevent_reset_sigchld_handler(void) {
// We could have any state at this point, depending on
// whether the default loop has been used. If it has,
// then always be in state 1 ("need to install)
if (sigchld_state) {
sigchld_state = 1;
}
}
#else
#define gevent_ev_default_loop ev_default_loop
static void gevent_install_sigchld_handler(void) { }
#endif

View File

@@ -0,0 +1,208 @@
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)
int vfd_open(long) except -1
void vfd_free(int)
cdef extern from "libev.h":
int EV_MINPRI
int EV_MAXPRI
int EV_VERSION_MAJOR
int EV_VERSION_MINOR
int EV_USE_FLOOR
int EV_USE_CLOCK_SYSCALL
int EV_USE_REALTIME
int EV_USE_MONOTONIC
int EV_USE_NANOSLEEP
int EV_USE_SELECT
int EV_USE_POLL
int EV_USE_EPOLL
int EV_USE_KQUEUE
int EV_USE_PORT
int EV_USE_INOTIFY
int EV_USE_SIGNALFD
int EV_USE_EVENTFD
int EV_USE_4HEAP
int EV_USE_IOCP
int EV_SELECT_IS_WINSOCKET
int EV_UNDEF
int EV_NONE
int EV_READ
int EV_WRITE
int EV__IOFDSET
int EV_TIMER
int EV_PERIODIC
int EV_SIGNAL
int EV_CHILD
int EV_STAT
int EV_IDLE
int EV_PREPARE
int EV_CHECK
int EV_EMBED
int EV_FORK
int EV_CLEANUP
int EV_ASYNC
int EV_CUSTOM
int EV_ERROR
int EVFLAG_AUTO
int EVFLAG_NOENV
int EVFLAG_FORKCHECK
int EVFLAG_NOINOTIFY
int EVFLAG_SIGNALFD
int EVFLAG_NOSIGMASK
int EVBACKEND_SELECT
int EVBACKEND_POLL
int EVBACKEND_EPOLL
int EVBACKEND_KQUEUE
int EVBACKEND_DEVPOLL
int EVBACKEND_PORT
int EVBACKEND_IOCP
int EVBACKEND_ALL
int EVBACKEND_MASK
int EVRUN_NOWAIT
int EVRUN_ONCE
int EVBREAK_CANCEL
int EVBREAK_ONE
int EVBREAK_ALL
struct ev_loop:
int activecnt
int sig_pending
int backend_fd
int sigfd
unsigned int origflags
struct ev_io:
int fd
int events
struct ev_timer:
double at
struct ev_signal:
pass
struct ev_idle:
pass
struct ev_prepare:
pass
struct ev_check:
pass
struct ev_fork:
pass
struct ev_async:
pass
struct ev_child:
int pid
int rpid
int rstatus
struct stat:
int st_nlink
struct ev_stat:
stat attr
stat prev
double interval
int ev_version_major()
int ev_version_minor()
unsigned int ev_supported_backends()
unsigned int ev_recommended_backends()
unsigned int ev_embeddable_backends()
double ev_time()
void ev_set_syserr_cb(void *)
int ev_priority(void*)
void ev_set_priority(void*, int)
int ev_is_pending(void*)
int ev_is_active(void*)
void ev_io_init(ev_io*, void* callback, int fd, int events)
void ev_io_start(ev_loop*, ev_io*)
void ev_io_stop(ev_loop*, ev_io*)
void ev_feed_event(ev_loop*, void*, int)
void ev_timer_init(ev_timer*, void* callback, double, double)
void ev_timer_start(ev_loop*, ev_timer*)
void ev_timer_stop(ev_loop*, ev_timer*)
void ev_timer_again(ev_loop*, ev_timer*)
void ev_signal_init(ev_signal*, void* callback, int)
void ev_signal_start(ev_loop*, ev_signal*)
void ev_signal_stop(ev_loop*, ev_signal*)
void ev_idle_init(ev_idle*, void* callback)
void ev_idle_start(ev_loop*, ev_idle*)
void ev_idle_stop(ev_loop*, ev_idle*)
void ev_prepare_init(ev_prepare*, void* callback)
void ev_prepare_start(ev_loop*, ev_prepare*)
void ev_prepare_stop(ev_loop*, ev_prepare*)
void ev_check_init(ev_check*, void* callback)
void ev_check_start(ev_loop*, ev_check*)
void ev_check_stop(ev_loop*, ev_check*)
void ev_fork_init(ev_fork*, void* callback)
void ev_fork_start(ev_loop*, ev_fork*)
void ev_fork_stop(ev_loop*, ev_fork*)
void ev_async_init(ev_async*, void* callback)
void ev_async_start(ev_loop*, ev_async*)
void ev_async_stop(ev_loop*, ev_async*)
void ev_async_send(ev_loop*, ev_async*)
int ev_async_pending(ev_async*)
void ev_child_init(ev_child*, void* callback, int, int)
void ev_child_start(ev_loop*, ev_child*)
void ev_child_stop(ev_loop*, ev_child*)
void ev_stat_init(ev_stat*, void* callback, char*, double)
void ev_stat_start(ev_loop*, ev_stat*)
void ev_stat_stop(ev_loop*, ev_stat*)
ev_loop* ev_default_loop(unsigned int flags)
ev_loop* ev_loop_new(unsigned int flags)
void ev_loop_destroy(ev_loop*)
void ev_loop_fork(ev_loop*)
int ev_is_default_loop(ev_loop*)
unsigned int ev_iteration(ev_loop*)
unsigned int ev_depth(ev_loop*)
unsigned int ev_backend(ev_loop*)
void ev_verify(ev_loop*)
void ev_run(ev_loop*, int flags) nogil
double ev_now(ev_loop*)
void ev_now_update(ev_loop*)
void ev_ref(ev_loop*)
void ev_unref(ev_loop*)
void ev_break(ev_loop*, int)
unsigned int ev_pending_count(ev_loop*)
ev_loop* gevent_ev_default_loop(unsigned int flags)
void gevent_install_sigchld_handler()
void gevent_reset_sigchld_handler()

View File

@@ -0,0 +1,223 @@
#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
/*
* If libev on win32 is embedded, then we can use an
* arbitrary mapping between integer fds and OS
* handles. Then by defining special macros libev
* will use our functions.
*/
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
typedef struct vfd_entry_t
{
vfd_socket_t handle; /* OS handle, i.e. SOCKET */
int count; /* Reference count, 0 if free */
int next; /* Next free fd, -1 if last */
} vfd_entry;
#define VFD_INCREMENT 128
static int vfd_num = 0; /* num allocated fds */
static int vfd_max = 0; /* max allocated fds */
static int vfd_next = -1; /* next free fd for reuse */
static PyObject* vfd_map = NULL; /* map OS handle -> virtual fd */
static vfd_entry* vfd_entries = NULL; /* list of virtual fd entries */
#ifdef WITH_THREAD
static CRITICAL_SECTION* volatile vfd_lock = NULL;
static CRITICAL_SECTION* vfd_make_lock()
{
if (vfd_lock == NULL) {
/* must use malloc and not PyMem_Malloc here */
CRITICAL_SECTION* lock = malloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(lock);
if (InterlockedCompareExchangePointer(&vfd_lock, lock, NULL) != NULL) {
/* another thread initialized lock first */
DeleteCriticalSection(lock);
free(lock);
}
}
return vfd_lock;
}
#define VFD_LOCK_ENTER EnterCriticalSection(vfd_make_lock())
#define VFD_LOCK_LEAVE LeaveCriticalSection(vfd_lock)
#define VFD_GIL_DECLARE PyGILState_STATE ___save
#define VFD_GIL_ENSURE ___save = PyGILState_Ensure()
#define VFD_GIL_RELEASE PyGILState_Release(___save)
#else
#define VFD_LOCK_ENTER
#define VFD_LOCK_LEAVE
#define VFD_GIL_DECLARE
#define VFD_GIL_ENSURE
#define VFD_GIL_RELEASE
#endif
/*
* Given a virtual fd returns an OS handle or -1
* This function is speed critical, so it cannot use GIL
*/
static vfd_socket_t vfd_get(int fd)
{
int handle = -1;
VFD_LOCK_ENTER;
if (vfd_entries != NULL && fd >= 0 && fd < vfd_num)
handle = vfd_entries[fd].handle;
VFD_LOCK_LEAVE;
return handle;
}
#define EV_FD_TO_WIN32_HANDLE(fd) vfd_get((fd))
/*
* Given an OS handle finds or allocates a virtual fd
* Returns -1 on failure and sets Python exception if pyexc is non-zero
*/
static int vfd_open_(vfd_socket_t handle, int pyexc)
{
VFD_GIL_DECLARE;
int fd = -1;
unsigned long arg;
PyObject* key = NULL;
PyObject* value;
if (!pyexc) {
VFD_GIL_ENSURE;
}
if (ioctlsocket(handle, FIONREAD, &arg) != 0) {
if (pyexc)
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;
}
if (vfd_map == NULL) {
vfd_map = PyDict_New();
if (vfd_map == NULL)
goto done;
}
key = vfd_socket_object(handle);
/* check if it's already in the dict */
value = PyDict_GetItem(vfd_map, key);
if (value != NULL) {
/* is it safe to use PyInt_AS_LONG(value) here? */
fd = PyInt_AsLong(value);
if (fd >= 0) {
++vfd_entries[fd].count;
goto done;
}
}
/* use the free entry, if available */
if (vfd_next >= 0) {
fd = vfd_next;
vfd_next = vfd_entries[fd].next;
VFD_LOCK_ENTER;
goto allocated;
}
/* check if it would be out of bounds */
if (vfd_num >= FD_SETSIZE) {
/* libev's select doesn't support more that FD_SETSIZE fds */
if (pyexc)
PyErr_Format(PyExc_IOError, "cannot watch more than %d sockets", (int)FD_SETSIZE);
goto done;
}
/* allocate more space if needed */
VFD_LOCK_ENTER;
if (vfd_num >= vfd_max) {
int newsize = vfd_max + VFD_INCREMENT;
vfd_entry* entries = PyMem_Realloc(vfd_entries, sizeof(vfd_entry) * newsize);
if (entries == NULL) {
VFD_LOCK_LEAVE;
if (pyexc)
PyErr_NoMemory();
goto done;
}
vfd_entries = entries;
vfd_max = newsize;
}
fd = vfd_num++;
allocated:
/* vfd_lock must be acquired when entering here */
vfd_entries[fd].handle = handle;
vfd_entries[fd].count = 1;
VFD_LOCK_LEAVE;
value = PyInt_FromLong(fd);
PyDict_SetItem(vfd_map, key, value);
Py_DECREF(value);
done:
Py_XDECREF(key);
if (!pyexc) {
VFD_GIL_RELEASE;
}
return fd;
}
#define vfd_open(fd) vfd_open_((fd), 1)
#define EV_WIN32_HANDLE_TO_FD(handle) vfd_open_((handle), 0)
static void vfd_free_(int fd, int needclose)
{
VFD_GIL_DECLARE;
PyObject* key;
if (needclose) {
VFD_GIL_ENSURE;
}
if (fd < 0 || fd >= vfd_num)
goto done; /* out of bounds */
if (vfd_entries[fd].count <= 0)
goto done; /* free entry, ignore */
if (!--vfd_entries[fd].count) {
/* fd has just been freed */
vfd_socket_t handle = vfd_entries[fd].handle;
vfd_entries[fd].handle = -1;
vfd_entries[fd].next = vfd_next;
vfd_next = fd;
if (needclose)
closesocket(handle);
/* vfd_map is assumed to be != NULL */
key = vfd_socket_object(handle);
PyDict_DelItem(vfd_map, key);
Py_DECREF(key);
}
done:
if (needclose) {
VFD_GIL_RELEASE;
}
}
#define vfd_free(fd) vfd_free_((fd), 0)
#define EV_WIN32_CLOSE_FD(fd) vfd_free_((fd), 1)
#else
/*
* If libev on win32 is not embedded in gevent, then
* the only way to map vfds is to use the default of
* using runtime fds in libev. Note that it will leak
* fds, because there's no way of closing them safely
*/
#define vfd_get(fd) _get_osfhandle((fd))
#define vfd_open(fd) _open_osfhandle((fd), 0)
#define vfd_free(fd)
#endif
#else
/*
* On non-win32 platforms vfd_* are noop macros
*/
typedef int vfd_socket_t;
#define vfd_get(fd) (fd)
#define vfd_open(fd) ((int)(fd))
#define vfd_free(fd)
#endif

View File

@@ -0,0 +1,187 @@
/* copied from Python-2.7.2/Modules/posixmodule.c */
#include "structseq.h"
#define STRUCT_STAT struct stat
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
#define ST_BLKSIZE_IDX 13
#else
#define ST_BLKSIZE_IDX 12
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
#else
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
#else
#define ST_RDEV_IDX ST_BLOCKS_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
#else
#define ST_FLAGS_IDX ST_RDEV_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
#else
#define ST_GEN_IDX ST_FLAGS_IDX
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
#else
#define ST_BIRTHTIME_IDX ST_GEN_IDX
#endif
static PyObject* posixmodule = NULL;
static PyTypeObject* pStatResultType = NULL;
static PyObject* import_posixmodule(void)
{
if (!posixmodule) {
posixmodule = PyImport_ImportModule("posix");
}
return posixmodule;
}
static PyObject* import_StatResultType(void)
{
PyObject* p = NULL;
if (!pStatResultType) {
PyObject* module;
module = import_posixmodule();
if (module) {
p = PyObject_GetAttrString(module, "stat_result");
}
}
return p;
}
static void
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
{
PyObject *fval,*ival;
#if SIZEOF_TIME_T > SIZEOF_LONG
ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
#else
ival = PyInt_FromLong((long)sec);
#endif
if (!ival)
return;
fval = PyFloat_FromDouble(sec + 1e-9*nsec);
PyStructSequence_SET_ITEM(v, index, ival);
PyStructSequence_SET_ITEM(v, index+3, fval);
}
/* pack a system stat C structure into the Python stat tuple
(used by posix_stat() and posix_fstat()) */
static PyObject*
_pystat_fromstructstat(STRUCT_STAT *st)
{
unsigned long ansec, mnsec, cnsec;
PyObject *v;
PyTypeObject* StatResultType = (PyTypeObject*)import_StatResultType();
if (StatResultType == NULL) {
return NULL;
}
v = PyStructSequence_New(StatResultType);
if (v == NULL)
return NULL;
PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 1,
PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
#else
PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
#endif
#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
PyStructSequence_SET_ITEM(v, 2,
PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
#else
PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev));
#endif
PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid));
PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st->st_gid));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 6,
PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
#else
PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
#endif
#if defined(HAVE_STAT_TV_NSEC)
ansec = st->st_atim.tv_nsec;
mnsec = st->st_mtim.tv_nsec;
cnsec = st->st_ctim.tv_nsec;
#elif defined(HAVE_STAT_TV_NSEC2)
ansec = st->st_atimespec.tv_nsec;
mnsec = st->st_mtimespec.tv_nsec;
cnsec = st->st_ctimespec.tv_nsec;
#elif defined(HAVE_STAT_NSEC)
ansec = st->st_atime_nsec;
mnsec = st->st_mtime_nsec;
cnsec = st->st_ctime_nsec;
#else
ansec = mnsec = cnsec = 0;
#endif
fill_time(v, 7, st->st_atime, ansec);
fill_time(v, 8, st->st_mtime, mnsec);
fill_time(v, 9, st->st_ctime, cnsec);
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
PyInt_FromLong((long)st->st_blksize));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
PyInt_FromLong((long)st->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
PyInt_FromLong((long)st->st_rdev));
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
PyInt_FromLong((long)st->st_gen));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
{
PyObject *val;
unsigned long bsec,bnsec;
bsec = (long)st->st_birthtime;
#ifdef HAVE_STAT_TV_NSEC2
bnsec = st->st_birthtimespec.tv_nsec;
#else
bnsec = 0;
#endif
val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
val);
}
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
PyInt_FromLong((long)st->st_flags));
#endif
if (PyErr_Occurred()) {
Py_DECREF(v);
return NULL;
}
return v;
}