track embedded python distribution
This commit is contained in:
0
python/gevent/libev/__init__.py
Normal file
0
python/gevent/libev/__init__.py
Normal file
75
python/gevent/libev/_corecffi_build.py
Normal file
75
python/gevent/libev/_corecffi_build.py
Normal 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()
|
||||
226
python/gevent/libev/_corecffi_cdef.c
Normal file
226
python/gevent/libev/_corecffi_cdef.c
Normal 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);
|
||||
45
python/gevent/libev/_corecffi_source.c
Normal file
45
python/gevent/libev/_corecffi_source.c
Normal 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.
|
||||
}
|
||||
}
|
||||
225
python/gevent/libev/callbacks.c
Normal file
225
python/gevent/libev/callbacks.c
Normal 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 */
|
||||
43
python/gevent/libev/callbacks.h
Normal file
43
python/gevent/libev/callbacks.h
Normal 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) { }
|
||||
1134
python/gevent/libev/corecext.ppyx
Normal file
1134
python/gevent/libev/corecext.ppyx
Normal file
File diff suppressed because it is too large
Load Diff
2110
python/gevent/libev/corecext.pyx
Normal file
2110
python/gevent/libev/corecext.pyx
Normal file
File diff suppressed because it is too large
Load Diff
1132
python/gevent/libev/corecffi.py
Normal file
1132
python/gevent/libev/corecffi.py
Normal file
File diff suppressed because it is too large
Load Diff
33465
python/gevent/libev/gevent.corecext.c
Normal file
33465
python/gevent/libev/gevent.corecext.c
Normal file
File diff suppressed because it is too large
Load Diff
66
python/gevent/libev/libev.h
Normal file
66
python/gevent/libev/libev.h
Normal 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
|
||||
208
python/gevent/libev/libev.pxd
Normal file
208
python/gevent/libev/libev.pxd
Normal 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()
|
||||
223
python/gevent/libev/libev_vfd.h
Normal file
223
python/gevent/libev/libev_vfd.h
Normal 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
|
||||
187
python/gevent/libev/stathelper.c
Normal file
187
python/gevent/libev/stathelper.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user