Merge pull request #4620 from murgatroid99/ruby_auth_plugin_event_loop

Use specific ruby thread to handle auth metadata plugin callbacks
pull/4648/head
Craig Tiller 9 years ago
commit 9a781b7e56
  1. 27
      src/ruby/ext/grpc/rb_call_credentials.c
  2. 153
      src/ruby/ext/grpc/rb_event_thread.c
  3. 37
      src/ruby/ext/grpc/rb_event_thread.h

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -38,8 +38,10 @@
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include "rb_call.h"
#include "rb_event_thread.h"
#include "rb_grpc.h"
/* grpc_rb_cCallCredentials is the ruby class that proxies
@ -87,7 +89,7 @@ static VALUE grpc_rb_call_credentials_callback_rescue(VALUE args,
return result;
}
static void *grpc_rb_call_credentials_callback_with_gil(void *param) {
static void grpc_rb_call_credentials_callback_with_gil(void *param) {
callback_params *const params = (callback_params *)param;
VALUE auth_uri = rb_str_new_cstr(params->context.service_url);
/* Pass the arguments to the proc in a hash, which currently only has they key
@ -113,21 +115,20 @@ static void *grpc_rb_call_credentials_callback_with_gil(void *param) {
params->callback(params->user_data, md_ary.metadata, md_ary.count, status,
error_details);
grpc_metadata_array_destroy(&md_ary);
return NULL;
gpr_free(params);
}
static void grpc_rb_call_credentials_plugin_get_metadata(
void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void *user_data) {
callback_params params;
params.get_metadata = (VALUE)state;
params.context = context;
params.user_data = user_data;
params.callback = cb;
rb_thread_call_with_gvl(grpc_rb_call_credentials_callback_with_gil,
(void*)(&params));
callback_params *params = gpr_malloc(sizeof(callback_params));
params->get_metadata = (VALUE)state;
params->context = context;
params->user_data = user_data;
params->callback = cb;
grpc_rb_event_queue_enqueue(grpc_rb_call_credentials_callback_with_gil,
(void*)(params));
}
static void grpc_rb_call_credentials_plugin_destroy(void *state) {
@ -300,6 +301,8 @@ void Init_grpc_call_credentials() {
grpc_rb_call_credentials_compose, -1);
id_callback = rb_intern("__callback");
grpc_rb_event_queue_thread_start();
}
/* Gets the wrapped grpc_call_credentials from the ruby wrapper */

@ -0,0 +1,153 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "rb_event_thread.h"
#include <stdbool.h>
#include <ruby/ruby.h>
#include <ruby/thread.h>
#include <grpc/support/alloc.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#include <grpc/support/log.h>
typedef struct grpc_rb_event {
// callback will be called with argument while holding the GVL
void (*callback)(void*);
void *argument;
struct grpc_rb_event *next;
} grpc_rb_event;
typedef struct grpc_rb_event_queue {
grpc_rb_event *head;
grpc_rb_event *tail;
gpr_mu mu;
gpr_cv cv;
// Indicates that the thread should stop waiting
bool abort;
} grpc_rb_event_queue;
static grpc_rb_event_queue event_queue;
void grpc_rb_event_queue_enqueue(void (*callback)(void*),
void *argument) {
grpc_rb_event *event = gpr_malloc(sizeof(grpc_rb_event));
event->callback = callback;
event->argument = argument;
event->next = NULL;
gpr_mu_lock(&event_queue.mu);
if (event_queue.tail == NULL) {
event_queue.head = event_queue.tail = event;
} else {
event_queue.tail->next = event;
event_queue.tail = event;
}
gpr_cv_signal(&event_queue.cv);
gpr_mu_unlock(&event_queue.mu);
}
static grpc_rb_event *grpc_rb_event_queue_dequeue() {
grpc_rb_event *event;
if (event_queue.head == NULL) {
event = NULL;
} else {
event = event_queue.head;
if (event_queue.head->next == NULL) {
event_queue.head = event_queue.tail = NULL;
} else {
event_queue.head = event_queue.head->next;
}
}
return event;
}
static void grpc_rb_event_queue_destroy() {
gpr_mu_destroy(&event_queue.mu);
gpr_cv_destroy(&event_queue.cv);
}
static void *grpc_rb_wait_for_event_no_gil(void *param) {
grpc_rb_event *event = NULL;
gpr_mu_lock(&event_queue.mu);
while ((event = grpc_rb_event_queue_dequeue()) == NULL) {
gpr_cv_wait(&event_queue.cv,
&event_queue.mu,
gpr_inf_future(GPR_CLOCK_REALTIME));
if (event_queue.abort) {
gpr_mu_unlock(&event_queue.mu);
return NULL;
}
}
gpr_mu_unlock(&event_queue.mu);
return event;
}
static void grpc_rb_event_unblocking_func(void *arg) {
gpr_mu_lock(&event_queue.mu);
event_queue.abort = true;
gpr_cv_signal(&event_queue.cv);
gpr_mu_unlock(&event_queue.mu);
}
/* This is the implementation of the thread that handles auth metadata plugin
* events */
static VALUE grpc_rb_event_thread(VALUE arg) {
grpc_rb_event *event;
while(true) {
event = (grpc_rb_event*)rb_thread_call_without_gvl(
grpc_rb_wait_for_event_no_gil, NULL,
grpc_rb_event_unblocking_func, NULL);
if (event == NULL) {
// Indicates that the thread needs to shut down
break;
} else {
event->callback(event->argument);
gpr_free(event);
}
}
grpc_rb_event_queue_destroy();
return Qnil;
}
void grpc_rb_event_queue_thread_start() {
event_queue.head = event_queue.tail = NULL;
event_queue.abort = false;
gpr_mu_init(&event_queue.mu);
gpr_cv_init(&event_queue.cv);
rb_thread_create(grpc_rb_event_thread, NULL);
}

@ -0,0 +1,37 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
void grpc_rb_event_queue_thread_start();
void grpc_rb_event_queue_enqueue(void (*callback)(void*),
void *argument);
Loading…
Cancel
Save