Esempio n. 1
0
static VALUE
wait_for_thread(void *data)
{
    struct BlockingThread* thr = (struct BlockingThread *) data;
    char c;
    
    if (read(thr->rdfd, &c, 1) < 1) {
        rb_thread_wait_fd(thr->rdfd);
        while (read(thr->rdfd, &c, 1) < 1 && rb_io_wait_readable(thr->rdfd) == Qtrue) {
            ;
        }
    }

    return Qnil;
}
Esempio n. 2
0
static VALUE method_zkrb_get_next_event(VALUE self, VALUE blocking) {
  // dbg.h
  check_debug(!is_closed(self), "we are closed, not trying to get event");

  char buf[64];
  FETCH_DATA_PTR(self, zk);

  for (;;) {
    check_debug(!is_closed(self), "we're closed in the middle of method_zkrb_get_next_event, bailing");

    zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);

    if (event == NULL) {
      if (NIL_P(blocking) || (blocking == Qfalse)) {
        goto error;
      }
      else {
        // if we're shutting down, don't enter this section, we don't want to block
        check_debug(!is_shutting_down(self), "method_zkrb_get_next_event, we're shutting down, don't enter blocking section");

        int fd = zk->queue->pipe_read;
        ssize_t bytes_read = 0;

        // wait for an fd to become readable, opposite of rb_thread_fd_writable
        rb_thread_wait_fd(fd);

        // clear all bytes here, we'll catch all the events on subsequent calls
        // (until we run out of events)
        bytes_read = read(fd, buf, sizeof(buf));

        if (bytes_read == -1) {
          rb_raise(rb_eRuntimeError, "read failed: %d", errno);
        }

        zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue);

        continue;
      }
    }

    VALUE hash = zkrb_event_to_ruby(event);
    zkrb_event_free(event);
    return hash;
  }

  error:
    return Qnil;
}
Esempio n. 3
0
static VALUE method_get_next_event(VALUE self, VALUE blocking) {
  char buf[64];
  FETCH_DATA_PTR(self, zk);

  for (;;) {

    // we use the is_running(self) method here because it allows us to have a
    // ruby-land semaphore that we can also use in the java extension
    //
    if (is_closed(self) || !is_running(self)) {
      zkrb_debug_inst(self, "is_closed(self): %d, is_running(self): %d, method_get_next_event is exiting loop", is_closed(self), is_running(self));
      return Qnil;  // this case for shutdown
    }

    zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);

    /* Wait for an event using rb_thread_select() on the queue's pipe */
    if (event == NULL) {
      if (NIL_P(blocking) || (blocking == Qfalse)) { 
        return Qnil; // no event for us
      } 
      else {
        int fd = zk->queue->pipe_read;
        ssize_t bytes_read = 0;

        // wait for an fd to become readable, opposite of rb_thread_fd_writable
        rb_thread_wait_fd(fd);

        bytes_read = read(fd, buf, sizeof(buf));

        if (bytes_read == -1) {
          rb_raise(rb_eRuntimeError, "read failed: %d", errno);
        }

        zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue);

        continue;
      }
    }

    VALUE hash = zkrb_event_to_ruby(event);
    zkrb_event_free(event);
    return hash;
  }
}
Esempio n. 4
0
static VALUE
dnssd_service_process(VALUE self) {
  DNSServiceRef *client;

  get(cDNSSDService, self, DNSServiceRef, client);

  if (client == NULL) {
    /* looks like this thread has already been stopped */
    return Qnil;
  }

  rb_thread_wait_fd(DNSServiceRefSockFD(*client));

  if (rb_ivar_get(self, dnssd_iv_continue) == Qfalse)
    return Qnil;

  DNSServiceErrorType e = DNSServiceProcessResult(*client);
  dnssd_check_error_code(e);

  return self;
}
Esempio n. 5
0
static
VALUE kl_read_loop(VALUE vfd)
{
    int fd = FIX2INT(vfd);

    int ret, done;
    struct input_event ev;

    int brek = 0;
    while(!brek) {
        
        done = 0;
        rb_thread_wait_fd(fd);

        while(!done) {

            ret = read(fd, &ev, sizeof(struct input_event));

            if(ret == -1) {

                if (rb_io_wait_readable(fd) == Qfalse)
                    rb_raise(rb_eStandardError, "read error");

            } else {

                if(ev.type == 1) {
                    if(rb_yield_values(2, INT2FIX(ev.code), INT2FIX(ev.value)) != Qtrue)
                        brek = 1;
                }
                done = 1;

            }
        }
    }

    return Qnil;
}
Esempio n. 6
0
static VALUE Lorcon_capture_loop(int argc, VALUE *argv, VALUE self) {
	struct rldev *rld;
	int count = 0;
	int p = 0;
	VALUE v_cnt;
	VALUE ret;
	int fd;
	
	Data_Get_Struct(self, struct rldev, rld);

	if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
		count = FIX2INT(v_cnt);
	} else {
		count = -1;
	}

	fd = lorcon_get_selectable_fd(rld->context);
	if(fd < 0 ) {
		rb_raise(rb_eRuntimeError,
				 "LORCON context could not provide a pollable descriptor "
				 "and we need one for the threaded dispatch loop");
	}
	
	while (p < count || count <= 0) {
		ret = Lorcon_capture_next(self);
		if(TYPE(ret) == T_FIXNUM) return(ret);
		if(ret == Qnil) {
			rb_thread_wait_fd(fd);
		} else {
			rb_yield(ret);
			p++;
		}
	}
	
	return INT2FIX(p);
}
Esempio n. 7
0
/*
 * call-seq:
 *   unixsocket.recv_io([klass [, mode]]) => io
 *
 *   UNIXServer.open("/tmp/sock") {|serv|
 *     UNIXSocket.open("/tmp/sock") {|c|  
 *       s = serv.accept
 *
 *       c.send_io STDOUT 
 *       stdout = s.recv_io 
 *
 *       p STDOUT.fileno #=> 1
 *       p stdout.fileno #=> 7
 *
 *       stdout.puts "hello" # outputs "hello\n" to standard output.
 *     }
 *   }
 *
 */
static VALUE
unix_recv_io(int argc, VALUE *argv, VALUE sock)
{
    VALUE klass, mode;
    rb_io_t *fptr;
    struct iomsg_arg arg;
    struct iovec vec[2];
    char buf[1];

    int fd;
#if FD_PASSING_BY_MSG_CONTROL
    struct {
	struct cmsghdr hdr;
        char pad[8+sizeof(int)+8];
    } cmsg;
#endif

    rb_scan_args(argc, argv, "02", &klass, &mode);
    if (argc == 0)
	klass = rb_cIO;
    if (argc <= 1)
	mode = Qnil;

    GetOpenFile(sock, fptr);

    arg.msg.msg_name = NULL;
    arg.msg.msg_namelen = 0;

    vec[0].iov_base = buf;
    vec[0].iov_len = sizeof(buf);
    arg.msg.msg_iov = vec;
    arg.msg.msg_iovlen = 1;

#if FD_PASSING_BY_MSG_CONTROL
    arg.msg.msg_control = (caddr_t)&cmsg;
    arg.msg.msg_controllen = CMSG_SPACE(sizeof(int));
    arg.msg.msg_flags = 0;
    cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_RIGHTS;
    fd = -1;
    memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
#else
    arg.msg.msg_accrights = (caddr_t)&fd;
    arg.msg.msg_accrightslen = sizeof(fd);
    fd = -1;
#endif

    arg.fd = fptr->fd;
    rb_thread_wait_fd(arg.fd);
    if ((int)BLOCKING_REGION(recvmsg_blocking, &arg) == -1)
	rb_sys_fail("recvmsg(2)");

#if FD_PASSING_BY_MSG_CONTROL
    if (arg.msg.msg_controllen < sizeof(struct cmsghdr)) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
		 (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
    }
    if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_level=%d, %d expected)",
		 cmsg.hdr.cmsg_level, SOL_SOCKET);
    }
    if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_type=%d, %d expected)",
		 cmsg.hdr.cmsg_type, SCM_RIGHTS);
    }
    if (arg.msg.msg_controllen < CMSG_LEN(sizeof(int))) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
		 (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
    }
    if (CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
		 (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
    }
    if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
	rsock_discard_cmsg_resource(&arg.msg);
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (cmsg_len=%d, %d expected)",
		 (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
    }
#else
    if (arg.msg.msg_accrightslen != sizeof(fd)) {
	rb_raise(rb_eSocket,
		 "file descriptor was not passed (accrightslen) : %d != %d",
		 arg.msg.msg_accrightslen, (int)sizeof(fd));
    }
#endif

#if FD_PASSING_BY_MSG_CONTROL
    memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int));
#endif

    if (klass == Qnil)
	return INT2FIX(fd);
    else {
	ID for_fd;
	int ff_argc;
	VALUE ff_argv[2];
	CONST_ID(for_fd, "for_fd");
	ff_argc = mode == Qnil ? 1 : 2;
	ff_argv[0] = INT2FIX(fd);
	ff_argv[1] = mode;
        return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
    }
}
Esempio n. 8
0
static VALUE
ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
    SSL *ssl;
    int ilen, nread = 0;
    VALUE len, str;
    rb_io_t *fptr;

    rb_scan_args(argc, argv, "11", &len, &str);
    ilen = NUM2INT(len);
    if(NIL_P(str)) {
	str = rb_bstr_new();
    }
    else{
        StringValue(str);
	rb_str_modify(str);
	str = rb_str_bstr(str);
    }
    rb_bstr_resize(str, ilen);
    if(ilen == 0) return str;

    Data_Get_Struct(self, SSL, ssl);
    GetOpenFile(ossl_ssl_get_io(self), fptr);
    if (ssl) {
	if(!nonblock && SSL_pending(ssl) <= 0)
	    rb_thread_wait_fd(FPTR_TO_FD(fptr));
	for (;;){
	    nread = SSL_read(ssl, rb_bstr_bytes(str),
		    rb_bstr_length(str));
	    switch(ssl_get_error(ssl, nread)){
	    case SSL_ERROR_NONE:
		goto end;
	    case SSL_ERROR_ZERO_RETURN:
		rb_eof_error();
	    case SSL_ERROR_WANT_WRITE:
                write_would_block(nonblock);
                rb_io_wait_writable(FPTR_TO_FD(fptr));
                continue;
	    case SSL_ERROR_WANT_READ:
                read_would_block(nonblock);
                rb_io_wait_readable(FPTR_TO_FD(fptr));
		continue;
	    case SSL_ERROR_SYSCALL:
		if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
		rb_sys_fail(0);
	    default:
		ossl_raise(eSSLError, "SSL_read:");
	    }
        }
    }
    else {
        ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
        rb_warning("SSL session is not started yet.");
        return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
    }

  end:
    rb_bstr_resize(str, nread);
    OBJ_TAINT(str);

    return str;
}
Esempio n. 9
0
VALUE
rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
{
    rb_io_t *fptr;
    VALUE str, klass;
    struct recvfrom_arg arg;
    VALUE len, flg;
    long buflen;
    long slen;

    rb_scan_args(argc, argv, "11", &len, &flg);

    if (flg == Qnil) arg.flags = 0;
    else             arg.flags = NUM2INT(flg);
    buflen = NUM2INT(len);

    GetOpenFile(sock, fptr);
    if (rb_io_read_pending(fptr)) {
	rb_raise(rb_eIOError, "recv for buffered IO");
    }
    arg.fd = fptr->fd;
    arg.alen = (socklen_t)sizeof(arg.buf);

    arg.str = str = rb_tainted_str_new(0, buflen);
    klass = RBASIC(str)->klass;
    rb_obj_hide(str);

    while (rb_io_check_closed(fptr),
	   rb_thread_wait_fd(arg.fd),
	   (slen = BLOCKING_REGION_FD(recvfrom_blocking, &arg)) < 0) {
        if (!rb_io_wait_readable(fptr->fd)) {
            rb_sys_fail("recvfrom(2)");
        }
	if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) {
	    rb_raise(rb_eRuntimeError, "buffer string modified");
	}
    }

    rb_obj_reveal(str, klass);
    if (slen < RSTRING_LEN(str)) {
	rb_str_set_len(str, slen);
    }
    rb_obj_taint(str);
    switch (from) {
      case RECV_RECV:
	return str;
      case RECV_IP:
#if 0
	if (arg.alen != sizeof(struct sockaddr_in)) {
	    rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
	}
#endif
	if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
	    return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP));
	else
	    return rb_assoc_new(str, Qnil);

#ifdef HAVE_SYS_UN_H
      case RECV_UNIX:
        return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen));
#endif
      case RECV_SOCKET:
	return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, &arg.buf.addr, arg.alen));
      default:
	rb_bug("rsock_s_recvfrom called with bad value");
    }
}
Esempio n. 10
0
static VALUE
fs_watcher_wait_fd(VALUE _fd) {
	int fd = (int) _fd;
	rb_thread_wait_fd(fd);
	return Qnil;
}