aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/libuv/_corecffi_source.c
diff options
context:
space:
mode:
authorJames Taylor <user234683@users.noreply.github.com>2018-09-14 19:32:27 -0700
committerJames Taylor <user234683@users.noreply.github.com>2018-09-14 19:32:27 -0700
commit4212164e91ba2f49583cf44ad623a29b36db8f77 (patch)
tree47aefe3c0162f03e0c823b43873356f69c1cd636 /python/gevent/libuv/_corecffi_source.c
parent6ca20ff7010f2bafc7fefcb8cad982be27a8aeae (diff)
downloadyt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.tar.lz
yt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.tar.xz
yt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.zip
Windows: Use 32-bit distribution of python
Diffstat (limited to 'python/gevent/libuv/_corecffi_source.c')
-rw-r--r--python/gevent/libuv/_corecffi_source.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/python/gevent/libuv/_corecffi_source.c b/python/gevent/libuv/_corecffi_source.c
new file mode 100644
index 0000000..83fe82e
--- /dev/null
+++ b/python/gevent/libuv/_corecffi_source.c
@@ -0,0 +1,181 @@
+#include <string.h>
+#include "uv.h"
+
+typedef void* GeventWatcherObject;
+
+static int python_callback(GeventWatcherObject handle, int revents);
+static void python_queue_callback(uv_handle_t* watcher_ptr, int revents);
+static void python_handle_error(GeventWatcherObject handle, int revents);
+static void python_stop(GeventWatcherObject handle);
+
+static void _gevent_noop(void* handle) {}
+
+static void (*gevent_noop)(void* handle) = &_gevent_noop;
+
+static void _gevent_generic_callback1_unused(uv_handle_t* watcher, int arg)
+{
+ // Python code may set this to NULL or even change it
+ // out from under us, which would tend to break things.
+ GeventWatcherObject handle = watcher->data;
+ const int cb_result = python_callback(handle, arg);
+ 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, arg);
+ break;
+ case 1:
+ // Code to stop the event IF NEEDED. Note that if python_callback
+ // has disposed of the last reference to the handle,
+ // `watcher` could now be invalid/disposed memory!
+ if (!uv_is_active(watcher)) {
+ if (watcher->data != handle) {
+ if (watcher->data) {
+ // If Python set the data to NULL, then they
+ // expected to be stopped. That's fine.
+ // Otherwise, something weird happened.
+ fprintf(stderr,
+ "WARNING: gevent: watcher handle changed in callback "
+ "from %p to %p for watcher at %p of type %d\n",
+ handle, watcher->data, watcher, watcher->type);
+ // There's a very good chance that the object the
+ // handle referred to has been changed and/or the
+ // old handle has been deallocated (most common), so
+ // passing the old handle will crash. Instead we
+ // pass a sigil to let python distinguish this case.
+ python_stop(NULL);
+ }
+ }
+ else {
+ python_stop(handle);
+ }
+ }
+ break;
+ case 2:
+ // watcher is already stopped and dead, nothing to do.
+ break;
+ default:
+ fprintf(stderr,
+ "WARNING: gevent: Unexpected return value %d from Python callback "
+ "for watcher %p (of type %d) and handle %p\n",
+ cb_result,
+ watcher, watcher->type, handle);
+ // XXX: Possible leaking of resources here? Should we be
+ // closing the watcher?
+ }
+}
+
+
+static void _gevent_generic_callback1(uv_handle_t* watcher, int arg)
+{
+ python_queue_callback(watcher, arg);
+}
+
+static void _gevent_generic_callback0(uv_handle_t* handle)
+{
+ _gevent_generic_callback1(handle, 0);
+}
+
+static void _gevent_async_callback0(uv_async_t* handle)
+{
+ _gevent_generic_callback0((uv_handle_t*)handle);
+}
+
+static void _gevent_timer_callback0(uv_timer_t* handle)
+{
+ _gevent_generic_callback0((uv_handle_t*)handle);
+}
+
+static void _gevent_prepare_callback0(uv_prepare_t* handle)
+{
+ _gevent_generic_callback0((uv_handle_t*)handle);
+}
+
+static void _gevent_check_callback0(uv_check_t* handle)
+{
+ _gevent_generic_callback0((uv_handle_t*)handle);
+}
+
+static void _gevent_idle_callback0(uv_idle_t* handle)
+{
+ _gevent_generic_callback0((uv_handle_t*)handle);
+}
+
+static void _gevent_signal_callback1(uv_signal_t* handle, int signum)
+{
+ _gevent_generic_callback1((uv_handle_t*)handle, signum);
+}
+
+
+static void _gevent_poll_callback2(void* handle, int status, int events)
+{
+ _gevent_generic_callback1(handle, status < 0 ? status : events);
+}
+
+static void _gevent_fs_event_callback3(void* handle, const char* filename, int events, int status)
+{
+ _gevent_generic_callback1(handle, status < 0 ? status : events);
+}
+
+
+typedef struct _gevent_fs_poll_s {
+ uv_fs_poll_t handle;
+ uv_stat_t curr;
+ uv_stat_t prev;
+} gevent_fs_poll_t;
+
+static void _gevent_fs_poll_callback3(void* handlep, int status, const uv_stat_t* prev, const uv_stat_t* curr)
+{
+ // stat pointers are valid for this callback only.
+ // if given, copy them into our structure, where they can be reached
+ // from python, just like libev's watcher does, before calling
+ // the callback.
+
+ // The callback is invoked with status < 0 if path does not exist
+ // or is inaccessible. The watcher is not stopped but your
+ // callback is not called again until something changes (e.g. when
+ // the file is created or the error reason changes).
+ // In that case the fields will be 0 in curr/prev.
+
+
+ gevent_fs_poll_t* handle = (gevent_fs_poll_t*)handlep;
+ assert(status == 0);
+
+ handle->curr = *curr;
+ handle->prev = *prev;
+
+ _gevent_generic_callback1((uv_handle_t*)handle, 0);
+}
+
+static void gevent_uv_walk_callback_close(uv_handle_t* handle, void* arg)
+{
+ if( handle && !uv_is_closing(handle) ) {
+ uv_close(handle, NULL);
+ }
+}
+
+static void gevent_close_all_handles(uv_loop_t* loop)
+{
+ uv_walk(loop, gevent_uv_walk_callback_close, NULL);
+}
+
+static void gevent_zero_timer(uv_timer_t* handle)
+{
+ memset(handle, 0, sizeof(uv_timer_t));
+}
+
+static void gevent_zero_check(uv_check_t* handle)
+{
+ memset(handle, 0, sizeof(uv_check_t));
+}
+
+static void gevent_zero_prepare(uv_prepare_t* handle)
+{
+ memset(handle, 0, sizeof(uv_prepare_t));
+}
+
+static void gevent_zero_loop(uv_loop_t* handle)
+{
+ memset(handle, 0, sizeof(uv_loop_t));
+}