Beispiel #1
0
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
  struct nogvl_connect_args args;
  VALUE rv;
  GET_CLIENT(self);

  args.host = NIL_P(host) ? NULL : StringValuePtr(host);
  args.unix_socket = NIL_P(socket) ? NULL : StringValuePtr(socket);
  args.port = NIL_P(port) ? 0 : NUM2INT(port);
  args.user = NIL_P(user) ? NULL : StringValuePtr(user);
  args.passwd = NIL_P(pass) ? NULL : StringValuePtr(pass);
  args.db = NIL_P(database) ? NULL : StringValuePtr(database);
  args.mysql = wrapper->client;
  args.client_flag = NUM2ULONG(flags);

  rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
  if (rv == Qfalse) {
    while (rv == Qfalse && errno == EINTR && !mysql_errno(wrapper->client)) {
      errno = 0;
      rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
    }
    if (rv == Qfalse)
      return rb_raise_mysql2_error(wrapper);
  }

  wrapper->server_version = mysql_get_server_version(wrapper->client);
  wrapper->connected = 1;
  return self;
}
Beispiel #2
0
/*
  call-seq:
    insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'},
                                   :this_channel_is_insecure)
    creds = ...
    secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds)

  Creates channel instances. */
static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
  VALUE channel_args = Qnil;
  VALUE credentials = Qnil;
  VALUE target = Qnil;
  grpc_rb_channel* wrapper = NULL;
  grpc_channel* ch = NULL;
  grpc_channel_credentials* creds = NULL;
  char* target_chars = NULL;
  grpc_channel_args args;
  channel_init_try_register_stack stack;
  int stop_waiting_for_thread_start = 0;
  MEMZERO(&args, grpc_channel_args, 1);

  grpc_ruby_once_init();
  rb_thread_call_without_gvl(
      wait_until_channel_polling_thread_started_no_gil,
      &stop_waiting_for_thread_start,
      wait_until_channel_polling_thread_started_unblocking_func,
      &stop_waiting_for_thread_start);

  /* "3" == 3 mandatory args */
  rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials);

  TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
  target_chars = StringValueCStr(target);
  grpc_rb_hash_convert_to_channel_args(channel_args, &args);
  if (TYPE(credentials) == T_SYMBOL) {
    if (id_insecure_channel != SYM2ID(credentials)) {
      rb_raise(rb_eTypeError,
               "bad creds symbol, want :this_channel_is_insecure");
      return Qnil;
    }
    ch = grpc_insecure_channel_create(target_chars, &args, NULL);
  } else {
    wrapper->credentials = credentials;
    creds = grpc_rb_get_wrapped_channel_credentials(credentials);
    ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
  }

  GPR_ASSERT(ch);
  stack.channel = ch;
  stack.wrapper = wrapper;
  rb_thread_call_without_gvl(
      channel_init_try_register_connection_polling_without_gil, &stack, NULL,
      NULL);

  if (args.args != NULL) {
    xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */
  }
  if (ch == NULL) {
    rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s",
             target_chars);
    return Qnil;
  }
  rb_ivar_set(self, id_target, target);
  return self;
}
Beispiel #3
0
static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
  struct nogvl_connect_args args;
  time_t start_time, end_time;
  unsigned int elapsed_time, connect_timeout;
  VALUE rv;
  GET_CLIENT(self);

  args.host        = NIL_P(host)     ? NULL : StringValueCStr(host);
  args.unix_socket = NIL_P(socket)   ? NULL : StringValueCStr(socket);
  args.port        = NIL_P(port)     ? 0    : NUM2INT(port);
  args.user        = NIL_P(user)     ? NULL : StringValueCStr(user);
  args.passwd      = NIL_P(pass)     ? NULL : StringValueCStr(pass);
  args.db          = NIL_P(database) ? NULL : StringValueCStr(database);
  args.mysql       = wrapper->client;
  args.client_flag = NUM2ULONG(flags);

  if (wrapper->connect_timeout)
    time(&start_time);
  rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
  if (rv == Qfalse) {
    while (rv == Qfalse && errno == EINTR) {
      if (wrapper->connect_timeout) {
        time(&end_time);
        /* avoid long connect timeout from system time changes */
        if (end_time < start_time)
          start_time = end_time;
        elapsed_time = end_time - start_time;
        /* avoid an early timeout due to time truncating milliseconds off the start time */
        if (elapsed_time > 0)
          elapsed_time--;
        if (elapsed_time >= wrapper->connect_timeout)
          break;
        connect_timeout = wrapper->connect_timeout - elapsed_time;
        mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
      }
      errno = 0;
      rv = (VALUE) rb_thread_call_without_gvl(nogvl_connect, &args, RUBY_UBF_IO, 0);
    }
    /* restore the connect timeout for reconnecting */
    if (wrapper->connect_timeout)
      mysql_options(wrapper->client, MYSQL_OPT_CONNECT_TIMEOUT, &wrapper->connect_timeout);
    if (rv == Qfalse)
      return rb_raise_mysql2_error(wrapper);
  }

  wrapper->server_version = mysql_get_server_version(wrapper->client);
  wrapper->connected = 1;
  return self;
}
Beispiel #4
0
/* Wait until the channel's connectivity state becomes different from
 * "last_state", or "deadline" expires.
 * Returns true if the channel's connectivity state becomes different
 * from "last_state" within "deadline".
 * Returns false if "deadline" expires before the channel's connectivity
 * state changes from "last_state".
 * */
static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
                                                      VALUE last_state,
                                                      VALUE deadline) {
  grpc_rb_channel* wrapper = NULL;
  watch_state_stack stack;
  void* op_success = 0;

  TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);

  if (wrapper->bg_wrapped == NULL) {
    rb_raise(rb_eRuntimeError, "closed!");
    return Qnil;
  }

  if (!FIXNUM_P(last_state)) {
    rb_raise(
        rb_eTypeError,
        "bad type for last_state. want a GRPC::Core::ChannelState constant");
    return Qnil;
  }

  stack.bg_wrapped = wrapper->bg_wrapped;
  stack.deadline = grpc_rb_time_timeval(deadline, 0),
  stack.last_state = NUM2LONG(last_state);

  op_success = rb_thread_call_without_gvl(
      wait_for_watch_state_op_complete_without_gvl, &stack,
      wait_for_watch_state_op_complete_unblocking_func, wrapper->bg_wrapped);

  return op_success ? Qtrue : Qfalse;
}
Beispiel #5
0
/*
 * @overload poll(is_stderr: false, timeout: -1)
 *  Poll a channel for data to read.
 *  @since 0.1.0
 *  @param [Boolean] is_stderr A boolean to select the stderr stream.
 *  @param [Fixnum] timeout A timeout in milliseconds. A negative value means an
 *    infinite timeout.
 *  @return [Fixnum, nil] The number of bytes available for reading. +nil+ if
 *    timed out.
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_poll_timeout
 */
static VALUE m_poll(int argc, VALUE *argv, VALUE self) {
  ChannelHolder *holder;
  VALUE opts;
  const ID table[] = {id_stderr, id_timeout};
  VALUE kwvals[sizeof(table) / sizeof(*table)];
  struct nogvl_poll_args args;

  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  rb_scan_args(argc, argv, "00:", &opts);
  rb_get_kwargs(opts, table, 0, 2, kwvals);
  if (kwvals[0] == Qundef) {
    args.is_stderr = 0;
  } else {
    args.is_stderr = RTEST(kwvals[0]) ? 1 : 0;
  }
  if (kwvals[1] == Qundef) {
    args.timeout = -1;
  } else {
    Check_Type(kwvals[1], T_FIXNUM);
    args.timeout = FIX2INT(kwvals[1]);
  }

  args.channel = holder->channel;
  rb_thread_call_without_gvl(nogvl_poll, &args, RUBY_UBF_IO, NULL);
  RAISE_IF_ERROR(args.rc);

  if (args.rc == SSH_EOF) {
    return Qnil;
  } else {
    return INT2FIX(args.rc);
  }
}
Beispiel #6
0
/*
 * @overload read(count, is_stderr: false, timeout: -1)
 *  Read data from a channel.
 *  @since 0.1.0
 *  @param [Fixnum] count The count of bytes to be read.
 *  @param [Boolean] is_stderr Read from the stderr flow or not.
 *  @param [Fixnum] timeout A timeout in seconds. +-1+ means infinite timeout.
 *  @return [String] Data read from the channel.
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_read_timeout
 */
static VALUE m_read(int argc, VALUE *argv, VALUE self) {
  ChannelHolder *holder;
  VALUE count, opts;
  const ID table[] = {id_stderr, id_timeout};
  VALUE kwvals[sizeof(table) / sizeof(*table)];
  struct nogvl_read_args args;
  VALUE ret;

  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  rb_scan_args(argc, argv, "10:", &count, &opts);
  Check_Type(count, T_FIXNUM);
  rb_get_kwargs(opts, table, 0, 2, kwvals);
  if (kwvals[0] == Qundef) {
    args.is_stderr = 0;
  } else {
    args.is_stderr = RTEST(kwvals[0]) ? 1 : 0;
  }
  if (kwvals[1] == Qundef) {
    args.timeout = -1;
  } else {
    Check_Type(kwvals[1], T_FIXNUM);
    args.timeout = FIX2INT(kwvals[1]);
  }
  args.channel = holder->channel;
  args.count = FIX2UINT(count);
  args.buf = ALLOC_N(char, args.count);
  rb_thread_call_without_gvl(nogvl_read, &args, RUBY_UBF_IO, NULL);

  ret = rb_utf8_str_new(args.buf, args.rc);
  ruby_xfree(args.buf);
  return ret;
}
Beispiel #7
0
static VALUE
na_add(VALUE self, VALUE other, VALUE repeat, void*(*func)(void *))
{
    volatile VALUE result;
    struct narray3 a;
    int i;

    Data_Get_Struct(self,narray_t,a.x);
    Data_Get_Struct(other,narray_t,a.y);
    if (a.x->size != a.y->size) {
        rb_raise(rb_eArgError,"size mismatch");
    }
    result = na_s_allocate(cNArray);
    Data_Get_Struct(result,narray_t,a.z);
    a.z->size = a.x->size;
    a.z->ptr = ALLOC_N(char,a.z->size*sizeof(double));
    a.stop = Qfalse;
    a.repeat = NUM2INT(repeat);
    for (i=0; i<a.repeat; i++) {
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
        rb_thread_call_without_gvl(func, &a, na_para_stop, &a);
#else
        func(&a);
#endif
    }
    return result;
}
Beispiel #8
0
int
rb_file_load_ok(const char *path)
{
    DWORD attr;
    int ret = 1;
    long len;
    wchar_t* wpath;

    wpath = mbstr_to_wstr(CP_UTF8, path, -1, &len);
    if (!wpath) return 0;

    attr = GetFileAttributesW(wpath);
    if (attr == INVALID_FILE_ATTRIBUTES ||
            (attr & FILE_ATTRIBUTE_DIRECTORY)) {
        ret = 0;
    }
    else {
        HANDLE h = (HANDLE)rb_thread_call_without_gvl(loadopen_func, (void *)wpath,
                   RUBY_UBF_IO, 0);
        if (h != INVALID_HANDLE_VALUE) {
            CloseHandle(h);
        }
        else {
            ret = 0;
        }
    }
    free(wpath);
    return ret;
}
Beispiel #9
0
static int rbthreads_wait_fd_read(int fd, int timeout) {
        struct uwsgi_rbthread urbt;
        urbt.fd = fd;
        urbt.timeout = timeout;
        rb_thread_call_without_gvl(rbthreads_wait_fd_read_do, &urbt, NULL, NULL);
        return urbt.ret;
}
Beispiel #10
0
static VALUE helium_event_thread(void *unused)
{
  struct helium_waiter_t waiter = {
    .callback = NULL,
    .abort = 0
  };

  while (waiter.abort == 0) {
    rb_thread_call_without_gvl(wait_for_callback, &waiter, &stop_waiting, &waiter);

    if (waiter.callback != NULL) {
      rb_thread_create(helium_callback_handler_thread, (void *)waiter.callback);
    }
  }

  return Qnil;
}

void Init_rbhelium()
{
  mHelium = rb_define_module("Helium");
  cConnection = rb_define_class_under(mHelium, "Connection", rb_cObject);
  rb_define_alloc_func(cConnection, helium_rb_allocate);
  rb_define_method(cConnection, "initialize", helium_rb_initialize, -1);
  rb_define_method(cConnection, "write", helium_rb_send, 3);
  rb_define_method(cConnection, "subscribe", helium_rb_subscribe, 2);
  rb_define_method(cConnection, "unsubscribe", helium_rb_unsubscribe, 1);
  rb_define_method(cConnection, "close", helium_rb_close, 0);
  rb_thread_create(helium_event_thread, NULL);
}
/* Shuts down and drains the completion queue if necessary.
 *
 * This is done when the ruby completion queue object is about to be GCed.
 */
static void grpc_rb_completion_queue_shutdown_drain(grpc_completion_queue *cq) {
  next_call_stack next_call;
  grpc_completion_type type;
  int drained = 0;
  MEMZERO(&next_call, next_call_stack, 1);

  grpc_completion_queue_shutdown(cq);
  next_call.cq = cq;
  next_call.event.type = GRPC_QUEUE_TIMEOUT;
  /* TODO: the timeout should be a module level constant that defaults
   * to gpr_inf_future(GPR_CLOCK_REALTIME).
   *
   * - at the moment this does not work, it stalls.  Using a small timeout like
   *   this one works, and leads to fast test run times; a longer timeout was
   *   causing unnecessary delays in the test runs.
   *
   * - investigate further, this is probably another example of C-level cleanup
   * not working consistently in all cases.
   */
  next_call.timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                   gpr_time_from_micros(5e3, GPR_TIMESPAN));
  do {
    rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
                               (void *)&next_call, NULL, NULL);
    type = next_call.event.type;
    if (type == GRPC_QUEUE_TIMEOUT) break;
    if (type != GRPC_QUEUE_SHUTDOWN) {
      ++drained;
      rb_warning("completion queue shutdown: %d undrained events", drained);
    }
  } while (type != GRPC_QUEUE_SHUTDOWN);
}
Beispiel #12
0
static void consumer_consume_loop(HermannInstanceConfig* consumerConfig) {
	rd_kafka_message_t *msg;
	TRACER("\n");

	while (consumerConfig->run) {
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
		msg = (rd_kafka_message_t *) rb_thread_blocking_region((rb_blocking_function_t *) consumer_recv_msg,
				consumerConfig,
				consumer_consume_stop_callback,
				consumerConfig);
#elif HAVE_RB_THREAD_CALL_WITHOUT_GVL
		msg = rb_thread_call_without_gvl(consumer_recv_msg,
				consumerConfig,
				consumer_consume_stop_callback,
				consumerConfig);
#else
		msg = consumer_recv_msg(consumerConfig);
#endif

		if ( msg ) {
			msg_consume(msg, consumerConfig);
			rd_kafka_message_destroy(msg);
		}
	}
}
Beispiel #13
0
// Poll channel connectivity states in background thread without the GIL.
static VALUE run_poll_channels_loop(VALUE arg) {
  (void)arg;
  gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread");
  rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL,
                             grpc_rb_event_unblocking_func, NULL);
  return Qnil;
}
Beispiel #14
0
static VALUE consumer_consume_loop(VALUE self) {
	HermannInstanceConfig* consumerConfig;
	rd_kafka_message_t *msg;

	Data_Get_Struct(self, HermannInstanceConfig, consumerConfig);

	TRACER("\n");

	while (consumerConfig->run) {
#if HAVE_RB_THREAD_BLOCKING_REGION && RUBY_API_VERSION_MAJOR < 2
		msg = (rd_kafka_message_t *) rb_thread_blocking_region((rb_blocking_function_t *) consumer_recv_msg,
				consumerConfig,
				consumer_consume_stop_callback,
				consumerConfig);
#elif HAVE_RB_THREAD_CALL_WITHOUT_GVL
		msg = rb_thread_call_without_gvl(consumer_recv_msg,
				consumerConfig,
				consumer_consume_stop_callback,
				consumerConfig);
#else
		msg = consumer_recv_msg(consumerConfig);
#endif

		if ( msg ) {
			msg_consume(msg, consumerConfig);
		}
	}

	return Qnil;
}
Beispiel #15
0
/*
 * Immediately disconnect from the server; normally the garbage collector
 * will disconnect automatically when a connection is no longer needed.
 * Explicitly closing this will free up server resources sooner than waiting
 * for the garbage collector.
 *
 * @return [nil]
 */
static VALUE rb_mysql_client_close(VALUE self) {
  GET_CLIENT(self);

  if (wrapper->connected) {
    rb_thread_call_without_gvl(nogvl_close, wrapper, RUBY_UBF_IO, 0);
  }

  return Qnil;
}
Beispiel #16
0
/* call-seq:
 *    client.ping
 *
 * Checks whether the connection to the server is working. If the connection
 * has gone down and auto-reconnect is enabled an attempt to reconnect is made.
 * If the connection is down and auto-reconnect is disabled, ping returns an
 * error.
 */
static VALUE rb_mysql_client_ping(VALUE self) {
  GET_CLIENT(self);

  if (!wrapper->connected) {
    return Qfalse;
  } else {
    return (VALUE)rb_thread_call_without_gvl(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
  }
}
Beispiel #17
0
VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) {
  mysql_stmt_wrapper *stmt_wrapper;
  VALUE rb_stmt;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *conn_enc;
#endif

  Check_Type(sql, T_STRING);

  rb_stmt = Data_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, rb_mysql_stmt_mark, rb_mysql_stmt_free, stmt_wrapper);
  {
    stmt_wrapper->client = rb_client;
    stmt_wrapper->refcount = 1;
    stmt_wrapper->closed = 0;
    stmt_wrapper->stmt = NULL;
  }

  // instantiate stmt
  {
    GET_CLIENT(rb_client);
    stmt_wrapper->stmt = mysql_stmt_init(wrapper->client);
#ifdef HAVE_RUBY_ENCODING_H
    conn_enc = rb_to_encoding(wrapper->encoding);
#endif
  }
  if (stmt_wrapper->stmt == NULL) {
    rb_raise(cMysql2Error, "Unable to initialize prepared statement: out of memory");
  }

  // set STMT_ATTR_UPDATE_MAX_LENGTH attr
  {
    my_bool truth = 1;
    if (mysql_stmt_attr_set(stmt_wrapper->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &truth)) {
      rb_raise(cMysql2Error, "Unable to initialize prepared statement: set STMT_ATTR_UPDATE_MAX_LENGTH");
    }
  }

  // call mysql_stmt_prepare w/o gvl
  {
    struct nogvl_prepare_statement_args args;
    args.stmt = stmt_wrapper->stmt;
    args.sql = sql;
#ifdef HAVE_RUBY_ENCODING_H
    // ensure the string is in the encoding the connection is expecting
    args.sql = rb_str_export_to_enc(args.sql, conn_enc);
#endif
    args.sql_ptr = RSTRING_PTR(sql);
    args.sql_len = RSTRING_LEN(sql);

    if ((VALUE)rb_thread_call_without_gvl(nogvl_prepare_statement, &args, RUBY_UBF_IO, 0) == Qfalse) {
      rb_raise_mysql2_stmt_error(stmt_wrapper);
    }
  }

  return rb_stmt;
}
Beispiel #18
0
static VALUE do_send_query(void *args) {
  struct nogvl_send_query_args *query_args = args;
  mysql_client_wrapper *wrapper = query_args->wrapper;
  if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
    /* an error occurred, we're not active anymore */
    MARK_CONN_INACTIVE(self);
    return rb_raise_mysql2_error(wrapper);
  }
  return Qnil;
}
Beispiel #19
0
/*
 * @overload send_eof
 *  Send EOF on the channel.
 *  @since 0.1.0
 *  @return [nil]
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_send_eof
 */
static VALUE m_send_eof(VALUE self) {
  ChannelHolder *holder;
  struct nogvl_channel_args args;

  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  args.channel = holder->channel;
  rb_thread_call_without_gvl(nogvl_send_eof, &args, RUBY_UBF_IO, NULL);
  RAISE_IF_ERROR(args.rc);
  return Qnil;
}
Beispiel #20
0
static VALUE component_create(VALUE self) {
    component_t *data;
    TypedData_Get_Struct(self, component_t, &data_type, data);

    qmlbind_value obj = rb_thread_call_without_gvl((void *(*)(void *))&qmlbind_component_create, data->component, RUBY_UBF_IO, NULL);
    VALUE result = rbqml_to_ruby(obj);
    qmlbind_value_release(obj);

    return result;
}
Beispiel #21
0
static int service(VALUE self, Connection* connection, enet_uint32 timeout)
{
  CallbackData data = {connection, timeout, -1};
  if (timeout > 0)
  { rb_thread_call_without_gvl(do_service, &data, RUBY_UBF_IO, NULL); }
  else
  { do_service(&data); }

  return data.result;
}
Beispiel #22
0
static VALUE initialize_ext(VALUE self) {
  GET_CLIENT(self);

  if ((VALUE)rb_thread_call_without_gvl(nogvl_init, wrapper, RUBY_UBF_IO, 0) == Qfalse) {
    /* TODO: warning - not enough memory? */
    return rb_raise_mysql2_error(wrapper);
  }

  wrapper->initialized = 1;
  return self;
}
Beispiel #23
0
/*
 * @overload request_exec(cmd)
 *  Run a shell command without an interactive shell.
 *  @since 0.1.0
 *  @param [String] cmd The command to execute
 *  @return [nil]
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_request_exec
 */
static VALUE m_request_exec(VALUE self, VALUE cmd) {
  ChannelHolder *holder;
  struct nogvl_request_exec_args args;

  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  args.channel = holder->channel;
  args.cmd = StringValueCStr(cmd);
  rb_thread_call_without_gvl(nogvl_request_exec, &args, RUBY_UBF_IO, NULL);
  RAISE_IF_ERROR(args.rc);
  return Qnil;
}
Beispiel #24
0
/* Perform the actual HTTP request by calling libcurl. */
static VALUE perform_request(VALUE self) {
  struct curl_state *state = get_curl_state(self);
  CURL* curl = state->handle;
  membuffer* header_buffer = NULL;
  membuffer* body_buffer = NULL;
  CURLcode ret = 0;

  state->interrupt = 0;  /* clear any interrupt flags */

  header_buffer = &state->header_buffer;
  body_buffer = &state->body_buffer;

  membuffer_clear(header_buffer);
  membuffer_clear(body_buffer);

  /* headers */
  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &session_write_handler);
  curl_easy_setopt(curl, CURLOPT_HEADERDATA, header_buffer);

  /* body */
  if (!state->download_file) {
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &session_write_handler);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
  }

#if (defined(HAVE_TBR) || defined(HAVE_TCWOGVL)) && defined(USE_TBR)
#if defined(HAVE_TCWOGVL)
  ret = (CURLcode) rb_thread_call_without_gvl(
          (void *(*)(void *)) curl_easy_perform, curl,
          RUBY_UBF_IO, 0
        );
#else
  ret = (CURLcode) rb_thread_blocking_region(
          (rb_blocking_function_t*) curl_easy_perform, curl,
          RUBY_UBF_IO, 0
        );
#endif
#else
  ret = curl_easy_perform(curl);
#endif

  if (CURLE_OK == ret) {
    VALUE header_str = membuffer_to_rb_str(header_buffer);
    VALUE body_str = Qnil;
    if (!state->download_file) { body_str = membuffer_to_rb_str(body_buffer); }
    
    curl_easy_setopt(curl, CURLOPT_COOKIELIST, "FLUSH"); // Flush cookies to the cookie jar
    
    return create_response(self, curl, header_str, body_str);
  } else {
    rb_raise(select_error(ret), "%s", state->error_buf);
  }
}
Beispiel #25
0
/* Note this is an API-level call; a wrapped channel's finalizer doesn't call
 * this */
static VALUE grpc_rb_channel_destroy(VALUE self) {
  grpc_rb_channel* wrapper = NULL;

  TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
  if (wrapper->bg_wrapped != NULL) {
    rb_thread_call_without_gvl(channel_safe_destroy_without_gil,
                               wrapper->bg_wrapped, NULL, NULL);
    wrapper->bg_wrapped = NULL;
  }

  return Qnil;
}
Beispiel #26
0
/* call-seq:
 *    client.async_result
 *
 * Returns the result for the last async issued query.
 */
static VALUE rb_mysql_client_async_result(VALUE self) {
  MYSQL_RES * result;
  VALUE resultObj;
  VALUE current, is_streaming;
  GET_CLIENT(self);

  /* if we're not waiting on a result, do nothing */
  if (NIL_P(wrapper->active_thread))
    return Qnil;

  REQUIRE_CONNECTED(wrapper);
  if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
    /* an error occurred, mark this connection inactive */
    MARK_CONN_INACTIVE(self);
    return rb_raise_mysql2_error(wrapper);
  }

  is_streaming = rb_hash_aref(rb_iv_get(self, "@current_query_options"), sym_stream);
  if (is_streaming == Qtrue) {
    result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_use_result, wrapper, RUBY_UBF_IO, 0);
  } else {
    result = (MYSQL_RES *)rb_thread_call_without_gvl(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
  }

  if (result == NULL) {
    if (mysql_errno(wrapper->client) != 0) {
      MARK_CONN_INACTIVE(self);
      rb_raise_mysql2_error(wrapper);
    }
    /* no data and no error, so query was not a SELECT */
    return Qnil;
  }

  current = rb_hash_dup(rb_iv_get(self, "@current_query_options"));
  (void)RB_GC_GUARD(current);
  Check_Type(current, T_HASH);
  resultObj = rb_mysql_result_to_obj(self, wrapper->encoding, current, result, Qnil);

  return resultObj;
}
Beispiel #27
0
/* Returns true if the thread is interrupted. */
static VALUE thread_spec_rb_thread_call_without_gvl(VALUE self) {
  int fds[2];
  void* ret;

  if (pipe(fds) == -1) {
    return Qfalse;
  }
  ret = rb_thread_call_without_gvl(blocking_gvl_func, (void*)(size_t)fds[0],
                                   unblock_gvl_func, (void*)(size_t)fds[1]);
  close(fds[0]);
  close(fds[1]);
  return (VALUE)ret;
}
Beispiel #28
0
/*
 * @overload get_exit_status
 *  Get the exit status of the channel.
 *  @since 0.1.0
 *  @return [Fixnum, nil] The exit status. +nil+ if no exit status has been
 *    returned.
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_get_exit_status
 */
static VALUE m_get_exit_status(VALUE self) {
  ChannelHolder *holder;
  struct nogvl_channel_args args;

  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  args.channel = holder->channel;
  rb_thread_call_without_gvl(nogvl_get_exit_status, &args, RUBY_UBF_IO, NULL);
  if (args.rc == -1) {
    return Qnil;
  } else {
    return INT2FIX(args.rc);
  }
}
Beispiel #29
0
/*
 * @overload write(data)
 *  Write data on the channel.
 *  @since 0.1.0
 *  @param [String] data Data to write.
 *  @return [Fixnum] The number of bytes written.
 *  @see http://api.libssh.org/stable/group__libssh__channel.html
 *    ssh_channel_write
 */
static VALUE m_write(VALUE self, VALUE data) {
  ChannelHolder *holder;
  struct nogvl_write_args args;

  Check_Type(data, T_STRING);
  TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder);
  args.channel = holder->channel;
  args.data = RSTRING_PTR(data);
  args.len = RSTRING_LEN(data);
  rb_thread_call_without_gvl(nogvl_write, &args, RUBY_UBF_IO, NULL);
  RAISE_IF_ERROR(args.rc);
  return INT2FIX(args.rc);
}
Beispiel #30
0
/* Blocks until the next event is available, and returns the event. */
static VALUE grpc_rb_completion_queue_next(VALUE self, VALUE timeout) {
  next_call_stack next_call;
  MEMZERO(&next_call, next_call_stack, 1);
  Data_Get_Struct(self, grpc_completion_queue, next_call.cq);
  next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
  next_call.event = NULL;
  rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
                             (void *)&next_call, NULL, NULL);
  if (next_call.event == NULL) {
    return Qnil;
  }
  return grpc_rb_new_event(next_call.event);
}