Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}