Пример #1
0
/*
 * call-seq:
 *   io.wait_writable          -> IO
 *   io.wait_writable(timeout) -> IO or nil
 *
 * Waits until IO writable is available or times out and returns self or
 * nil when EOF is reached.
 */
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    int i;
    VALUE timeout;
    struct timeval timerec;
    struct timeval *tv;

    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);
    rb_scan_args(argc, argv, "01", &timeout);
    if (NIL_P(timeout)) {
	tv = NULL;
    }
    else {
	timerec = rb_time_interval(timeout);
	tv = &timerec;
    }

    i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_OUT, tv);
    if (i < 0)
	rb_sys_fail(0);
    rb_io_check_closed(fptr);
    if (i & RB_WAITFD_OUT)
	return io;
    return Qnil;
}
Пример #2
0
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    int i;
    ioctl_arg n;
    VALUE timeout;
    struct timeval timerec;
    struct timeval *tv;

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    rb_scan_args(argc, argv, "01", &timeout);
    if (NIL_P(timeout)) {
	tv = NULL;
    }
    else {
	timerec = rb_time_interval(timeout);
	tv = &timerec;
    }

    if (rb_io_read_pending(fptr)) return Qtrue;
    if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
    i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv);
    if (i < 0)
	rb_sys_fail(0);
    rb_io_check_closed(fptr);
    if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
    if (n > 0) return io;
    return Qnil;
}
Пример #3
0
Файл: wait.c Проект: 7kaji/try
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
{
	struct timeval tv = rb_time_interval(timeout);
	int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;

	return rb_wait_for_single_fd(my_fileno(self), events, &tv);
}
Пример #4
0
/* emulate blocking connect behavior on EINTR or non-blocking socket */
static int
wait_connectable(int fd)
{
    int sockerr, revents;
    socklen_t sockerrlen;

    /* only to clear pending error */
    sockerrlen = (socklen_t)sizeof(sockerr);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
        return -1;

    /*
     * Stevens book says, successful finish turn on RB_WAITFD_OUT and
     * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
     * So it's enough to wait only RB_WAITFD_OUT and check the pending error
     * by getsockopt().
     *
     * Note: rb_wait_for_single_fd already retries on EINTR/ERESTART
     */
    revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);

    if (revents < 0)
        return -1;

    sockerrlen = (socklen_t)sizeof(sockerr);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
        return -1;

    switch (sockerr) {
      case 0:
      /*
       * be defensive in case some platforms set SO_ERROR on the original,
       * interrupted connect()
       */
      case EINTR:
#ifdef ERESTART
      case ERESTART:
#endif
      case EAGAIN:
#ifdef EINPROGRESS
      case EINPROGRESS:
#endif
#ifdef EALREADY
      case EALREADY:
#endif
#ifdef EISCONN
      case EISCONN:
#endif
	return 0; /* success */
      default:
        /* likely (but not limited to): ECONNREFUSED, ETIMEDOUT, EHOSTUNREACH */
        errno = sockerr;
        return -1;
    }

    return 0;
}
Пример #5
0
static int
wait_connectable(int fd)
{
    int sockerr;
    socklen_t sockerrlen;
    int revents;
    int ret;

    for (;;) {
	/*
	 * Stevens book says, succuessful finish turn on RB_WAITFD_OUT and
	 * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
	 */
	revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);

	if (revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) {
	    sockerrlen = (socklen_t)sizeof(sockerr);
	    ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);

	    /*
	     * Solaris getsockopt(SO_ERROR) return -1 and set errno
	     * in getsockopt(). Let's return immediately.
	     */
	    if (ret < 0)
		break;
	    if (sockerr == 0) {
		if (revents & RB_WAITFD_OUT)
		    break;
		else
		    continue;	/* workaround for winsock */
	    }

	    /* BSD and Linux use sockerr. */
	    errno = sockerr;
	    ret = -1;
	    break;
	}

	if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) {
	    ret = 0;
	    break;
	}
    }

    return ret;
}
Пример #6
0
static VALUE do_query(void *args) {
  struct async_query_args *async_args;
  struct timeval tv;
  struct timeval* tvp;
  long int sec;
  int retval;
  VALUE read_timeout;

  async_args = (struct async_query_args *)args;
  read_timeout = rb_iv_get(async_args->self, "@read_timeout");

  tvp = NULL;
  if (!NIL_P(read_timeout)) {
    Check_Type(read_timeout, T_FIXNUM);
    tvp = &tv;
    sec = FIX2INT(read_timeout);
    // TODO: support partial seconds?
    // also, this check is here for sanity, we also check up in Ruby
    if (sec >= 0) {
      tvp->tv_sec = sec;
    } else {
      rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
    }
    tvp->tv_usec = 0;
  }

  for(;;) {
    retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);

    if (retval == 0) {
      rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
    }

    if (retval < 0) {
      rb_sys_fail(0);
    }

    if (retval > 0) {
      break;
    }
  }

  return Qnil;
}