static void _cpu_wake_channel_and_read(EV_P_ struct ev_io *ev, int revents) { STATE; size_t sz, total, offset; ssize_t i; char *buf; OBJECT ret, ba, enc; struct thread_info *ti = (struct thread_info*)ev->data; ti->state->pending_events--; state = ti->state; if(NIL_P(ti->buffer)) { ret = I2N(ti->fd); } else { ba = string_get_data(ti->buffer); enc = string_get_encoding(ti->buffer); sz = (size_t)ti->count; if(enc == SYM("buffer")) { offset = N2I(string_get_bytes(ti->buffer)); } else { offset = 0; } /* Clamp the read size so we don't overrun */ total = SIZE_OF_BODY(ba) - offset - 1; if(total < sz) { sz = total; } buf = bytearray_byte_address(state, ba); buf += offset; while(1) { i = read(ti->fd, buf, sz); if(i == 0) { ret = Qnil; } else if(i == -1) { /* If we read and got nothing, go again. We must get something. It might be better to re-schedule this in libev and try again, but libev just said SOMETHING was there... */ if(errno == EINTR) continue; ret = lookuptable_fetch(state, state->global->errno_mapping, I2N(errno)); } else { buf[i] = 0; string_set_bytes(ti->buffer, I2N(i + offset)); ret = I2N(i); } break; } } cpu_channel_send(state, ti->c, ti->channel, ret); _cpu_event_unregister_info(state, ti); }
OBJECT subtend_load_library(STATE, cpu c, OBJECT path, OBJECT name) { dlhandle lib; char *c_path, *c_name; void (*ep)(void); char init[128] = "Init_"; char *sys_name; rni_nmc *nmc; int len; struct stat sb; char *end; nmc = NULL; /* Try to make room for 'Init_', the extension, and a null byte */ len = N2I(string_get_bytes(path)) + 21; sys_name = ALLOC_N(char, len); /* path is a string like 'ext/gzip', we turn that into 'ext/gzip.so' or whatever the library suffix is. */ c_path = rbx_string_as_cstr(state, path); strlcpy(sys_name, c_path, len); end = strrchr(sys_name, '.'); /* detect if the suffix is already there. */ if(end == NULL || strcmp(end++, LIBSUFFIX)) { strlcat(sys_name, LIBSUFFIX, len); } if(stat(sys_name, &sb) == 1) { XFREE(sys_name); return I2N(0); } /* Open it up. If this fails, then we just pretend like the library isn't there. */ lib = xdlopen(sys_name); if(!lib) { XFREE(sys_name); printf("Couldnt open '%s': %s\n", sys_name, xdlerror()); /* No need to raise an exception, it's not there. */ return I2N(0); } /* name is like 'gzip', we want 'Init_gzip' */ c_name = rbx_string_as_cstr(state, name); strlcat(init, c_name, sizeof(init)); /* Try and load the init function. */ ep = (void (*)(void))xdlsym(lib, init); if(!ep) { XFREE(sys_name); /* TODO: raise an exception that the library is missing the function. */ return I2N(1); } else { nmc = nmc_new_standalone(); /* Now we need to setup the 'global' context so that stuff like rb_define_method works. */ subtend_set_context(state, c, nmc); /* Now perform the call. */ (*ep)(); } /* * We can't close the library while there are references to the code * in it. For now, we just leak the library reference, but we need * to track it so we can clean them up at some point in the future. * */ if(nmc) XFREE(nmc); subtend_set_context(state, c, NULL); XFREE(sys_name); return Qtrue; }