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; }
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; }
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; } }
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; }
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; }
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); }
/* * 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); } }
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; }
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"); } }
static VALUE fs_watcher_wait_fd(VALUE _fd) { int fd = (int) _fd; rb_thread_wait_fd(fd); return Qnil; }