예제 #1
0
static int
error_handle(int ex)
{
    int status = EXIT_FAILURE;
    rb_thread_t *th = GET_THREAD();

    if (rb_threadptr_set_raised(th))
	return EXIT_FAILURE;
    switch (ex & TAG_MASK) {
      case 0:
	status = EXIT_SUCCESS;
	break;

      case TAG_RETURN:
	error_pos();
	warn_print(": unexpected return\n");
	break;
      case TAG_NEXT:
	error_pos();
	warn_print(": unexpected next\n");
	break;
      case TAG_BREAK:
	error_pos();
	warn_print(": unexpected break\n");
	break;
      case TAG_REDO:
	error_pos();
	warn_print(": unexpected redo\n");
	break;
      case TAG_RETRY:
	error_pos();
	warn_print(": retry outside of rescue clause\n");
	break;
      case TAG_THROW:
	/* TODO: fix me */
	error_pos();
	warn_printf(": unexpected throw\n");
	break;
      case TAG_RAISE: {
	VALUE errinfo = GET_THREAD()->errinfo;
	if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
	    status = sysexit_status(errinfo);
	}
	else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) {
	    /* no message when exiting by signal */
	}
	else {
	    error_print();
	}
	break;
      }
      case TAG_FATAL:
	error_print();
	break;
      default:
	rb_bug("Unknown longjmp status %d", ex);
	break;
    }
    rb_threadptr_reset_raised(th);
    return status;
}
예제 #2
0
static void
error_print(void)
{
    volatile VALUE errat = Qnil;		/* OK */
    rb_thread_t *th = GET_THREAD();
    VALUE errinfo = th->errinfo;
    int raised_flag = th->raised_flag;
    volatile VALUE eclass, e;
    const char *volatile einfo;
    volatile long elen;

    if (NIL_P(errinfo))
	return;
    rb_thread_raised_clear(th);

    PUSH_TAG();
    if (EXEC_TAG() == 0) {
	errat = get_backtrace(errinfo);
    }
    else {
	errat = Qnil;
    }
    if (EXEC_TAG())
	goto error;
    if (NIL_P(errat)) {
	const char *file = rb_sourcefile();
	int line = rb_sourceline();
	if (!file)
	    warn_printf("%d", line);
	else if (!line)
	    warn_printf("%s", file);
	else
	    warn_printf("%s:%d", file, line);
    }
    else if (RARRAY_LEN(errat) == 0) {
	error_pos();
    }
    else {
	VALUE mesg = RARRAY_PTR(errat)[0];

	if (NIL_P(mesg))
	    error_pos();
	else {
	    warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
	}
    }

    eclass = CLASS_OF(errinfo);
    if (EXEC_TAG() == 0) {
	e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
	StringValue(e);
	einfo = RSTRING_PTR(e);
	elen = RSTRING_LEN(e);
    }
    else {
	einfo = "";
	elen = 0;
    }
    if (EXEC_TAG())
	goto error;
    if (eclass == rb_eRuntimeError && elen == 0) {
	warn_print(": unhandled exception\n");
    }
    else {
	VALUE epath;

	epath = rb_class_name(eclass);
	if (elen == 0) {
	    warn_print(": ");
	    warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
	    warn_print("\n");
	}
	else {
	    char *tail = 0;
	    long len = elen;

	    if (RSTRING_PTR(epath)[0] == '#')
		epath = 0;
	    if ((tail = memchr(einfo, '\n', elen)) != 0) {
		len = tail - einfo;
		tail++;		/* skip newline */
	    }
	    warn_print(": ");
	    warn_print2(einfo, len);
	    if (epath) {
		warn_print(" (");
		warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
		warn_print(")\n");
	    }
	    if (tail) {
		warn_print2(tail, elen - len - 1);
		if (einfo[elen-1] != '\n') warn_print2("\n", 1);
	    }
	}
    }

    if (!NIL_P(errat)) {
	long i;
	long len = RARRAY_LEN(errat);
	VALUE *ptr = RARRAY_PTR(errat);
        int skip = eclass == rb_eSysStackError;

#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
#define TRACE_HEAD 8
#define TRACE_TAIL 5

	for (i = 1; i < len; i++) {
	    if (TYPE(ptr[i]) == T_STRING) {
		warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
	    }
	    if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
		warn_printf("\t ... %ld levels...\n",
			    len - TRACE_HEAD - TRACE_TAIL);
		i = len - TRACE_TAIL;
	    }
	}
    }
  error:
    POP_TAG();
    rb_thread_raised_set(th, raised_flag);
}
예제 #3
0
파일: load.c 프로젝트: k-term/lesson
/*
 * returns
 *  0: if already loaded (false)
 *  1: successfully loaded (true)
 * <0: not found (LoadError)
 * >1: exception
 */
int
rb_require_internal(VALUE fname, int safe)
{
    volatile int result = -1;
    rb_thread_t *th = GET_THREAD();
    volatile VALUE errinfo = th->errinfo;
    int state;
    struct {
	int safe;
    } volatile saved;
    char *volatile ftptr = 0;

    if (RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()) {
	RUBY_DTRACE_REQUIRE_ENTRY(StringValuePtr(fname),
				  rb_sourcefile(),
				  rb_sourceline());
    }

    PUSH_TAG();
    saved.safe = rb_safe_level();
    if ((state = EXEC_TAG()) == 0) {
	VALUE path;
	long handle;
	int found;

	rb_set_safe_level_force(safe);
	FilePathValue(fname);
	rb_set_safe_level_force(0);

	if (RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()) {
	    RUBY_DTRACE_FIND_REQUIRE_ENTRY(StringValuePtr(fname),
					   rb_sourcefile(),
					   rb_sourceline());
	}

	path = rb_str_encode_ospath(fname);
	found = search_required(path, &path, safe);

	if (RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()) {
	    RUBY_DTRACE_FIND_REQUIRE_RETURN(StringValuePtr(fname),
					    rb_sourcefile(),
					    rb_sourceline());
	}
	if (found) {
	    if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
		result = 0;
	    }
	    else if (!*ftptr) {
		rb_provide_feature(path);
		result = 1;
	    }
	    else {
		switch (found) {
		  case 'r':
		    rb_load_internal(path, 0);
		    break;

		  case 's':
		    handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
						    path, 0, path);
		    rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
		    break;
		}
		rb_provide_feature(path);
		result = 1;
	    }
	}
    }
    POP_TAG();
    load_unlock(ftptr, !state);

    rb_set_safe_level_force(saved.safe);
    if (state) {
	/* never TAG_RETURN */
	return state;
    }

    th->errinfo = errinfo;

    if (RUBY_DTRACE_REQUIRE_RETURN_ENABLED()) {
	RUBY_DTRACE_REQUIRE_RETURN(StringValuePtr(fname),
				  rb_sourcefile(),
				  rb_sourceline());
    }

    return result;
}
예제 #4
0
int
rb_w32_sleep(unsigned long msec)
{
    return w32_wait_events(0, 0, msec, GET_THREAD());
}
예제 #5
0
파일: safe.c 프로젝트: 4nkh/rhodes
void
rb_set_safe_level_force(int safe)
{
    GET_THREAD()->safe_level = safe;
}
예제 #6
0
파일: vm_backtrace.c 프로젝트: sho-h/ruby
VALUE
rb_make_backtrace(void)
{
    return rb_vm_backtrace_str_ary(GET_THREAD(), 0, 0);
}
예제 #7
0
파일: cont.c 프로젝트: qnighy/ruby-1.9.2p0
static void
cont_restore_1(rb_context_t *cont)
{
    rb_thread_t *th = GET_THREAD(), *sth = &cont->saved_thread;

    /* restore thread context */
    if (cont->type == CONTINUATION_CONTEXT) {
	/* continuation */
	VALUE fib;

	th->fiber = sth->fiber;
	fib = th->fiber ? th->fiber : th->root_fiber;

	if (fib) {
	    rb_fiber_t *fcont;
	    GetFiberPtr(fib, fcont);
	    th->stack_size = fcont->cont.saved_thread.stack_size;
	    th->stack = fcont->cont.saved_thread.stack;
	}
#ifdef CAPTURE_JUST_VALID_VM_STACK
	MEMCPY(th->stack, cont->vm_stack, VALUE, cont->vm_stack_slen);
	MEMCPY(th->stack + sth->stack_size - cont->vm_stack_clen,
	       cont->vm_stack + cont->vm_stack_slen, VALUE, cont->vm_stack_clen);
#else
	MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size);
#endif
    }
    else {
	/* fiber */
	th->stack = sth->stack;
	th->stack_size = sth->stack_size;
	th->local_storage = sth->local_storage;
	th->fiber = cont->self;
    }

    th->cfp = sth->cfp;
    th->safe_level = sth->safe_level;
    th->raised_flag = sth->raised_flag;
    th->state = sth->state;
    th->status = sth->status;
    th->tag = sth->tag;
    th->protect_tag = sth->protect_tag;
    th->errinfo = sth->errinfo;
    th->first_proc = sth->first_proc;

    /* restore machine stack */
#ifdef _M_AMD64
    {
	/* workaround for x64 SEH */
	jmp_buf buf;
	setjmp(buf);
	((_JUMP_BUFFER*)(&cont->jmpbuf))->Frame =
	    ((_JUMP_BUFFER*)(&buf))->Frame;
    }
#endif
    if (cont->machine_stack_src) {
	FLUSH_REGISTER_WINDOWS;
	MEMCPY(cont->machine_stack_src, cont->machine_stack,
	       VALUE, cont->machine_stack_size);
    }

#ifdef __ia64
    if (cont->machine_register_stack_src) {
	MEMCPY(cont->machine_register_stack_src, cont->machine_register_stack,
	       VALUE, cont->machine_register_stack_size);
    }
#endif

    ruby_longjmp(cont->jmpbuf, 1);
}
예제 #8
0
파일: load.c 프로젝트: 217/ruby
static void
rb_load_internal(VALUE fname, int wrap)
{
    int state;
    rb_thread_t *th = GET_THREAD();
    volatile VALUE wrapper = th->top_wrapper;
    volatile VALUE self = th->top_self;
    volatile int loaded = FALSE;
    volatile int mild_compile_error;
#ifndef __GNUC__
    rb_thread_t *volatile th0 = th;
#endif

    th->errinfo = Qnil; /* ensure */

    if (!wrap) {
	rb_secure(4);		/* should alter global state */
	th->top_wrapper = 0;
    }
    else {
	/* load in anonymous module as toplevel */
	th->top_self = rb_obj_clone(rb_vm_top_self());
	th->top_wrapper = rb_module_new();
	rb_extend_object(th->top_self, th->top_wrapper);
    }

    mild_compile_error = th->mild_compile_error;
    PUSH_TAG();
    state = EXEC_TAG();
    if (state == 0) {
	NODE *node;
	VALUE iseq;

	th->mild_compile_error++;
	node = (NODE *)rb_load_file(RSTRING_PTR(fname));
	loaded = TRUE;
	iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse);
	th->mild_compile_error--;
	rb_iseq_eval(iseq);
    }
    POP_TAG();

#ifndef __GNUC__
    th = th0;
    fname = RB_GC_GUARD(fname);
#endif
    th->mild_compile_error = mild_compile_error;
    th->top_self = self;
    th->top_wrapper = wrapper;

    if (!loaded) {
	rb_exc_raise(GET_THREAD()->errinfo);
    }
    if (state) {
	rb_vm_jump_tag_but_local_jump(state, Qundef);
    }

    if (!NIL_P(GET_THREAD()->errinfo)) {
	/* exception during load */
	rb_exc_raise(th->errinfo);
    }
}
예제 #9
0
static void
sol_thread_fetch_registers (int regno)
{
  thread_t thread;
  td_thrhandle_t thandle;
  td_err_e val;
  prgregset_t gregset;
  prfpregset_t fpregset;
#if 0
  int xregsize;
  caddr_t xregset;
#endif

  if (!is_thread (inferior_ptid))
    {				/* LWP: pass the request on to procfs.c */
      if (target_has_execution)
	procfs_ops.to_fetch_registers (regno);
      else
	orig_core_ops.to_fetch_registers (regno);
      return;
    }

  /* Solaris thread: convert inferior_ptid into a td_thrhandle_t */

  thread = GET_THREAD (inferior_ptid);

  if (thread == 0)
    error ("sol_thread_fetch_registers:  thread == 0");

  val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
  if (val != TD_OK)
    error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
	   td_err_string (val));

  /* Get the integer regs */

  val = p_td_thr_getgregs (&thandle, gregset);
  if (val != TD_OK
      && val != TD_PARTIALREG)
    error ("sol_thread_fetch_registers: td_thr_getgregs %s",
	   td_err_string (val));

  /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
     are saved (by a thread context switch).  */

  /* And, now the fp regs */

  val = p_td_thr_getfpregs (&thandle, &fpregset);
  if (val != TD_OK
      && val != TD_NOFPREGS)
    error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
	   td_err_string (val));

/* Note that we must call supply_{g fp}regset *after* calling the td routines
   because the td routines call ps_lget* which affect the values stored in the
   registers array.  */

  supply_gregset  ((gdb_gregset_t *)  &gregset);
  supply_fpregset ((gdb_fpregset_t *) &fpregset);

#if 0
/* thread_db doesn't seem to handle this right */
  val = td_thr_getxregsize (&thandle, &xregsize);
  if (val != TD_OK && val != TD_NOXREGS)
    error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
	   td_err_string (val));

  if (val == TD_OK)
    {
      xregset = alloca (xregsize);
      val = td_thr_getxregs (&thandle, xregset);
      if (val != TD_OK)
	error ("sol_thread_fetch_registers: td_thr_getxregs %s",
	       td_err_string (val));
    }
#endif
}
예제 #10
0
static void
sol_thread_store_registers (int regno)
{
  thread_t thread;
  td_thrhandle_t thandle;
  td_err_e val;
  prgregset_t  gregset;
  prfpregset_t fpregset;
#if 0
  int xregsize;
  caddr_t xregset;
#endif

  if (!is_thread (inferior_ptid))
    {				/* LWP: pass the request on to procfs.c */
      procfs_ops.to_store_registers (regno);
      return;
    }

  /* Solaris thread: convert inferior_ptid into a td_thrhandle_t */

  thread = GET_THREAD (inferior_ptid);

  val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
  if (val != TD_OK)
    error ("sol_thread_store_registers: td_ta_map_id2thr %s",
	   td_err_string (val));

  if (regno != -1)
    {				/* Not writing all the regs */
      /* save new register value */
      char* old_value = (char*) alloca (REGISTER_SIZE);
      memcpy (old_value, &registers[REGISTER_BYTE (regno)], REGISTER_SIZE);

      val = p_td_thr_getgregs (&thandle, gregset);
      if (val != TD_OK)
	error ("sol_thread_store_registers: td_thr_getgregs %s",
	       td_err_string (val));
      val = p_td_thr_getfpregs (&thandle, &fpregset);
      if (val != TD_OK)
	error ("sol_thread_store_registers: td_thr_getfpregs %s",
	       td_err_string (val));

      /* restore new register value */
      memcpy (&registers[REGISTER_BYTE (regno)], old_value, REGISTER_SIZE);

#if 0
/* thread_db doesn't seem to handle this right */
      val = td_thr_getxregsize (&thandle, &xregsize);
      if (val != TD_OK && val != TD_NOXREGS)
	error ("sol_thread_store_registers: td_thr_getxregsize %s",
	       td_err_string (val));

      if (val == TD_OK)
	{
	  xregset = alloca (xregsize);
	  val = td_thr_getxregs (&thandle, xregset);
	  if (val != TD_OK)
	    error ("sol_thread_store_registers: td_thr_getxregs %s",
		   td_err_string (val));
	}
#endif
    }

  fill_gregset  ((gdb_gregset_t *)  &gregset,  regno);
  fill_fpregset ((gdb_fpregset_t *) &fpregset, regno);

  val = p_td_thr_setgregs (&thandle, gregset);
  if (val != TD_OK)
    error ("sol_thread_store_registers: td_thr_setgregs %s",
	   td_err_string (val));
  val = p_td_thr_setfpregs (&thandle, &fpregset);
  if (val != TD_OK)
    error ("sol_thread_store_registers: td_thr_setfpregs %s",
	   td_err_string (val));

#if 0
/* thread_db doesn't seem to handle this right */
  val = td_thr_getxregsize (&thandle, &xregsize);
  if (val != TD_OK && val != TD_NOXREGS)
    error ("sol_thread_store_registers: td_thr_getxregsize %s",
	   td_err_string (val));

  /* Should probably do something about writing the xregs here, but what are
     they? */
#endif
}
예제 #11
0
/**
 * This is the main routine responsible for replicating our GL state
 * for a new VNC viewer.  Called when we detect that a new VNC viewer
 * has been started.
 * \param ipaddress  the IP address where the new viewer is running.
 */
void
replicatespuReplicate(int ipaddress) 
{
	GET_THREAD(thread);
	struct in_addr addr;
	char *hosturl;
	char *ipstring;
	int i, r_slot;
	int serverPort;

	crDebug("Replicate SPU: Enter replicatespuReplicate(ipaddress=0x%x)", ipaddress);

	replicatespuFlushAll( (void *)thread );

#ifdef CHROMIUM_THREADSAFE_notyet
	crLockMutex(&_ReplicateMutex);
#endif

	/*
	 * Find empty slot.
	 * Slot 0 is the dummy slot (a non-existant server on devnull connection)
	 */
	for (r_slot = 1; r_slot < CR_MAX_REPLICANTS; r_slot++) {
		if (!IS_CONNECTED(replicate_spu.rserver[r_slot].conn))
			break;
	}
	if (r_slot == CR_MAX_REPLICANTS) {
		crWarning("Replicate SPU: no more replicant slots available");
		return;
	}

	/**
	 ** OK, now rserver[r_slot] is free for use.
	 **/

	/*
	 * At this time, we can only support one VNC viewer per host.
	 * Check for that here.
	 */
	for (i = 1; i < CR_MAX_REPLICANTS; i++) {
		if (replicate_spu.ipnumbers[i] == ipaddress) {
			CRConnection *conn = replicate_spu.rserver[i].conn;
			/* If the connection appears to be active, it may actually be a dangling
			 * connection.  Try flushing it now.  If flushing fails, the connection
			 * type will definitely be CR_NO_CONNECTION (which we test below).
			 */
			if (conn) {
				if (conn->type != CR_NO_CONNECTION) {
					FlushConnection(i);
				}
				if (conn->type != CR_NO_CONNECTION) {
					crWarning("Replicate SPU: Can't connect to multiple VNC viewers on one host.");
#if 0
					/* The above test isn't 100% reliable and can prevent successful
					 * restart of a viewer on a host.  For now, just print warning and
					 * continue.
					 */
					return;
#endif
				}
			}
		}
	}

	replicate_spu.ipnumbers[r_slot] = ipaddress;

	serverPort = replicate_spu.chromium_start_port + r_slot;

	if (replicate_spu.vncAvailable) {
		/* Send a ChromiumStart message to the VNC Server.  The VNC Server will
		 * in turn send a ChromiumStart message to all the attached VNC viewers.
		 * The VNC Viewer/Chromium module will tell its crserver that there's
		 * a new OpenGL client.
		 * We pass the mothership port and crserver port in this message.
		 */
		char protocol[100], hostname[1000];
		const char *mothershipURL;
		unsigned short mothershipPort;
		mothershipURL = crGetenv("CRMOTHERSHIP");
		crDebug("Replicate SPU: CRMOTHERSHIP env var = %s", mothershipURL);
		if (mothershipURL)
			crParseURL(mothershipURL, protocol, hostname, &mothershipPort,
								 DEFAULT_MOTHERSHIP_PORT);
		else
			mothershipPort = DEFAULT_MOTHERSHIP_PORT;
		crDebug("Replicate SPU: Sending ChromiumStart msg to VNC server, port=%d",
						serverPort);

		if (!XVncChromiumStart(replicate_spu.glx_display, ipaddress,
													 serverPort, mothershipPort)) {
			 crWarning("Replicate SPU: XVncChromiumStart() call failed");
		}
	}

	addr.s_addr = ipaddress;
	ipstring = inet_ntoa(addr);
	hosturl = crAlloc(crStrlen(ipstring) + 9);
	sprintf(hosturl, "tcpip://%s", ipstring);

	crDebug("Replicate SPU attaching to %s on port %d", hosturl, serverPort);

	/* connect to the remote VNC server */
	replicate_spu.rserver[r_slot].name = crStrdup( replicate_spu.name );
	replicate_spu.rserver[r_slot].buffer_size = replicate_spu.buffer_size;
	replicate_spu.rserver[r_slot].conn
		= crNetConnectToServer( hosturl, serverPort,
														replicate_spu.rserver[r_slot].buffer_size, 1);

	if (!replicate_spu.rserver[r_slot].conn) {
		crWarning("Replicate SPU: failed to connect to %s", hosturl);
		return;
	}

	CRASSERT(replicate_spu.rserver[r_slot].conn);

	/*
	 * Setup the the packer flush function.  While replicating state to
	 * a particular server we definitely don't want to do any broadcast
	 * flushing!
	 */
	crPackFlushFunc( thread->packer, replicatespuFlushOnePacker );
	crPackSendHugeFunc( thread->packer, replicatespuHugeOnePacker );

	NewServerIndex = r_slot;

	/*
	 * Create server-side windows and contexts by walking tables of app windows
	 * and contexts.  Note that windows can be created in random order,
	 * but contexts must be created in the order they were originally
	 * created, or shared contexts will break.
	 */
	crHashtableWalk(replicate_spu.windowTable, replicatespuReplicateWindow, thread);
	crListApply(replicate_spu.contextList, replicatespuReplicateContext, thread);

	/* MakeCurrent, the current context */
	if (thread->currentContext) {
		int serverWindow = thread->currentContext->currentWindow->id[r_slot];
		int serverContext = thread->currentContext->rserverCtx[r_slot];
		if (replicate_spu.swap)
			crPackMakeCurrentSWAP(serverWindow, 0, serverContext);
	 	else
			crPackMakeCurrent(serverWindow, 0, serverContext);

		crStateMakeCurrent( thread->currentContext->State );
	}

	/*
	 * Set window sizes
	 */
	crHashtableWalk(replicate_spu.windowTable, replicatespuResizeWindows, thread);
	replicatespuFlushOne(thread, NewServerIndex);

	/*
	 * restore normal, broadcasting packer flush function now.
	 */
	crPackFlushFunc( thread->packer, replicatespuFlush );
	crPackSendHugeFunc( thread->packer, replicatespuHuge );

	NewServerIndex = -1;

	crDebug("Replicate SPU: leaving replicatespuReplicate");

#ifdef CHROMIUM_THREADSAFE_notyet
	crUnlockMutex(&_ReplicateMutex);
#endif
}
예제 #12
0
 rb_thread_t *GET_THREAD2(void)
 {
   ruby_current_thread = ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()));
   return GET_THREAD();
 }
예제 #13
0
static void
args_setup_kw_parameters(VALUE* const passed_values, const int passed_keyword_len, const VALUE *const passed_keywords,
			 const rb_iseq_t * const iseq, VALUE * const locals)
{
    const ID *acceptable_keywords = iseq->body->param.keyword->table;
    const int req_key_num = iseq->body->param.keyword->required_num;
    const int key_num = iseq->body->param.keyword->num;
    const VALUE * const default_values = iseq->body->param.keyword->default_values;
    VALUE missing = 0;
    int i, di, found = 0;
    int unspecified_bits = 0;
    VALUE unspecified_bits_value = Qnil;

    for (i=0; i<req_key_num; i++) {
	ID key = acceptable_keywords[i];
	if (args_setup_kw_parameters_lookup(key, &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
	    found++;
	}
	else {
	    if (!missing) missing = rb_ary_tmp_new(1);
	    rb_ary_push(missing, ID2SYM(key));
	}
    }

    if (missing) argument_kw_error(GET_THREAD(), iseq, "missing", missing);

    for (di=0; i<key_num; i++, di++) {
	if (args_setup_kw_parameters_lookup(acceptable_keywords[i], &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
	    found++;
	}
	else {
	    if (default_values[di] == Qundef) {
		locals[i] = Qnil;

		if (LIKELY(i < 32)) { /* TODO: 32 -> Fixnum's max bits */
		    unspecified_bits |= 0x01 << di;
		}
		else {
		    if (NIL_P(unspecified_bits_value)) {
			/* fixnum -> hash */
			int j;
			unspecified_bits_value = rb_hash_new();

			for (j=0; j<32; j++) {
			    if (unspecified_bits & (0x01 << j)) {
				rb_hash_aset(unspecified_bits_value, INT2FIX(j), Qtrue);
			    }
			}
		    }
		    rb_hash_aset(unspecified_bits_value, INT2FIX(di), Qtrue);
		}
	    }
	    else {
		locals[i] = default_values[di];
	    }
	}
    }

    if (iseq->body->param.flags.has_kwrest) {
	const int rest_hash_index = key_num + 1;
	locals[rest_hash_index] = make_unused_kw_hash(passed_keywords, passed_keyword_len, passed_values, FALSE);
    }
    else {
	if (found != passed_keyword_len) {
	    VALUE keys = make_unused_kw_hash(passed_keywords, passed_keyword_len, passed_values, TRUE);
	    argument_kw_error(GET_THREAD(), iseq, "unknown", keys);
	}
    }

    if (NIL_P(unspecified_bits_value)) {
	unspecified_bits_value = INT2FIX(unspecified_bits);
    }
    locals[key_num] = unspecified_bits_value;
}
예제 #14
0
/*
 * Many operating systems allow signals to be sent to running
 * processes. Some signals have a defined effect on the process, while
 * others may be trapped at the code level and acted upon. For
 * example, your process may trap the USR1 signal and use it to toggle
 * debugging, and may use TERM to initiate a controlled shutdown.
 *
 *     pid = fork do
 *       Signal.trap("USR1") do
 *         $debug = !$debug
 *         puts "Debug now: #$debug"
 *       end
 *       Signal.trap("TERM") do
 *         puts "Terminating..."
 *         shutdown()
 *       end
 *       # . . . do some work . . .
 *     end
 *
 *     Process.detach(pid)
 *
 *     # Controlling program:
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("USR1", pid)
 *     # ...
 *     Process.kill("TERM", pid)
 *
 * produces:
 *     Debug now: true
 *     Debug now: false
 *    Terminating...
 *
 * The list of available signal names and their interpretation is
 * system dependent. Signal delivery semantics may also vary between
 * systems; in particular signal delivery may not always be reliable.
 */
void
Init_signal(void)
{
    VALUE mSignal = rb_define_module("Signal");

    rb_define_global_function("trap", sig_trap, -1);
    rb_define_module_function(mSignal, "trap", sig_trap, -1);
    rb_define_module_function(mSignal, "list", sig_list, 0);
    rb_define_module_function(mSignal, "signame", sig_signame, 1);

    rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
    rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
    rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
    rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);

    /* At this time, there is no subthread. Then sigmask guarantee atomics. */
    rb_disable_interrupt();

    install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
    install_sighandler(SIGHUP, sighandler);
#endif
#ifdef SIGQUIT
    install_sighandler(SIGQUIT, sighandler);
#endif
#ifdef SIGTERM
    install_sighandler(SIGTERM, sighandler);
#endif
#ifdef SIGALRM
    install_sighandler(SIGALRM, sighandler);
#endif
#ifdef SIGUSR1
    install_sighandler(SIGUSR1, sighandler);
#endif
#ifdef SIGUSR2
    install_sighandler(SIGUSR2, sighandler);
#endif

    if (!ruby_enable_coredump) {
#ifdef SIGBUS
	install_sighandler(SIGBUS, (sighandler_t)sigbus);
#endif
#ifdef SIGILL
	install_sighandler(SIGILL, (sighandler_t)sigill);
#endif
#ifdef SIGSEGV
# ifdef USE_SIGALTSTACK
	rb_register_sigaltstack(GET_THREAD());
# endif
	install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
#endif
    }
#ifdef SIGPIPE
    install_sighandler(SIGPIPE, SIG_IGN);
#endif

#if defined(SIGCLD)
    init_sigchld(SIGCLD);
#elif defined(SIGCHLD)
    init_sigchld(SIGCHLD);
#endif

    rb_enable_interrupt();
}
예제 #15
0
/**
 * Implementation of SwapBuffers for tilesorter
 *
 * \param window
 * \param flags
 */
void TILESORTSPU_APIENTRY tilesortspu_SwapBuffers( GLint window, GLint flags )
{
	GET_THREAD(thread);
	GLint writeback = tilesort_spu.num_servers;
	WindowInfo *winInfo;
	int serverWindow;

	tilesortspuFlush( thread );

	winInfo = tilesortspuGetWindowInfo(window, 0);
	CRASSERT(winInfo);
	/* NOTE: winInfo->server[n].window should be the same for all n! */
	serverWindow = winInfo->server[0].window;

	/* Here's where we force quad-buffered stereo rendering.
	 * We use an X trick to make the app draw each frame twice.
	 */
	if (winInfo->forceQuadBuffering) {
		if (winInfo->parity == 0) {
			/* we're swapping after drawing an even-numbered frame.
			 * Even frames are for left eye, odd frames are for right eye.
			 * Now, switch draw buffer to the right.
			 */
			/*
			crDebug("Swap: done with left.  Send expose to 0x%x",
							(int) winInfo->xwin);
			*/
			tilesortspu_DrawBuffer(GL_BACK_RIGHT);
			/*
			 * Trigger drawing the right view by sending an expose event to
			 * the app to trick it into redrawing.
			 */
#ifdef WINDOWS
			/** XXX \todo is there a Window equivalent here??? */
#elif defined(Darwin)
			/** XXX \todo is there a Darwin equivalent here??? */
#else
			CRASSERT(winInfo->dpy);
			CRASSERT(winInfo->xwin);
			XClearArea( winInfo->dpy, winInfo->xwin, 0, 0,
				    winInfo->lastWidth, winInfo->lastHeight,
				    True );
			XSync(winInfo->dpy, 0);
#endif
		}
		else
		{
			/*
			crDebug("Swap: done with right, now left");
			*/
			/* We're swapping after drawing an odd frame.
			 * Now, switch draw buffer back to the left.
			 */
			tilesortspu_DrawBuffer(GL_BACK_LEFT);
		}
		/* flip parity bit for next frame */
		winInfo->parity = !winInfo->parity;

		/* only swap prior to even (left) frames */
		if (winInfo->parity)
			return;
	}

	if (tilesort_spu.swap)
		crPackSwapBuffersSWAP( serverWindow, flags );
	else
		crPackSwapBuffers( serverWindow, flags );

	if (tilesort_spu.syncOnSwap)
	{
		if (tilesort_spu.swap)
			crPackWritebackSWAP( &writeback );
		else
			crPackWriteback( &writeback );
	}

	tilesortspuBroadcastGeom(0);
	tilesortspuShipBuffers();

	if (tilesort_spu.syncOnSwap)
	{
		while(writeback)
			crNetRecv();
	}

	/* want to emit a parameteri here */
	if (tilesort_spu.emit_GATHER_POST_SWAPBUFFERS)
	{
		if (tilesort_spu.swap)
			crPackChromiumParameteriCRSWAP(GL_GATHER_POST_SWAPBUFFERS_CR, serverWindow);
		else
			crPackChromiumParameteriCR(GL_GATHER_POST_SWAPBUFFERS_CR, serverWindow);
	}
}
예제 #16
0
VALUE
rb_f_kill(int argc, const VALUE *argv)
{
#ifndef HAVE_KILLPG
#define killpg(pg, sig) kill(-(pg), (sig))
#endif
    int negative = 0;
    int sig;
    int i;
    VALUE str;
    const char *s;

    rb_secure(2);
    rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);

    switch (TYPE(argv[0])) {
      case T_FIXNUM:
	sig = FIX2INT(argv[0]);
	break;

      case T_SYMBOL:
	str = rb_sym2str(argv[0]);
	goto str_signal;

      case T_STRING:
	str = argv[0];
      str_signal:
	s = RSTRING_PTR(str);
	if (s[0] == '-') {
	    negative++;
	    s++;
	}
	if (strncmp(signame_prefix, s, sizeof(signame_prefix)) == 0)
	    s += 3;
	if ((sig = signm2signo(s)) == 0) {
	    long ofs = s - RSTRING_PTR(str);
	    if (ofs) str = rb_str_subseq(str, ofs, RSTRING_LEN(str)-ofs);
	    rb_raise(rb_eArgError, "unsupported name `SIG%"PRIsVALUE"'", str);
	}

	if (negative)
	    sig = -sig;
	break;

      default:
	str = rb_check_string_type(argv[0]);
	if (!NIL_P(str)) {
	    goto str_signal;
	}
	rb_raise(rb_eArgError, "bad signal type %s",
		 rb_obj_classname(argv[0]));
	break;
    }

    if (argc <= 1) return INT2FIX(0);

    if (sig < 0) {
	sig = -sig;
	for (i=1; i<argc; i++) {
	    if (killpg(NUM2PIDT(argv[i]), sig) < 0)
		rb_sys_fail(0);
	}
    }
    else {
	const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1;
	int wakeup = 0;

	for (i=1; i<argc; i++) {
	    rb_pid_t pid = NUM2PIDT(argv[i]);

	    if ((sig != 0) && (self != -1) && (pid == self)) {
		int t;
		/*
		 * When target pid is self, many caller assume signal will be
		 * delivered immediately and synchronously.
		 */
		switch (sig) {
		  case SIGSEGV:
#ifdef SIGBUS
		  case SIGBUS:
#endif
#ifdef SIGKILL
		  case SIGKILL:
#endif
#ifdef SIGSTOP
		  case SIGSTOP:
#endif
		    ruby_kill(pid, sig);
		    break;
		  default:
		    t = signal_ignored(sig);
		    if (t) {
			if (t < 0 && kill(pid, sig))
			    rb_sys_fail(0);
			break;
		    }
		    signal_enque(sig);
		    wakeup = 1;
		}
	    }
	    else if (kill(pid, sig) < 0) {
		rb_sys_fail(0);
	    }
	}
	if (wakeup) {
	    rb_threadptr_check_signal(GET_VM()->main_thread);
	}
    }
    rb_thread_execute_interrupts(rb_thread_current());

    return INT2FIX(i-1);
}
예제 #17
0
파일: vm_dump.c 프로젝트: sho-h/ruby
void
rb_vmdebug_stack_dump_raw_current(void)
{
    rb_thread_t *th = GET_THREAD();
    rb_vmdebug_stack_dump_raw(th, th->cfp);
}
예제 #18
0
파일: safe.c 프로젝트: 4nkh/rhodes
int
rb_safe_level(void)
{
    return GET_THREAD()->safe_level;
}
예제 #19
0
static void
gvl_atfork(rb_vm_t *vm)
{
    gvl_init(vm);
    gvl_acquire(vm, GET_THREAD());
}
예제 #20
0
파일: vm_backtrace.c 프로젝트: sho-h/ruby
VALUE
rb_vm_backtrace_object(void)
{
    return backtrace_object(GET_THREAD());
}
예제 #21
0
int
rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout)
{
    return w32_wait_events(events, num, timeout, GET_THREAD());
}
예제 #22
0
파일: vm_backtrace.c 프로젝트: sho-h/ruby
/*
 *  call-seq:
 *     caller_locations(start=1, length=nil)	-> array or nil
 *     caller_locations(range)			-> array or nil
 *
 *  Returns the current execution stack---an array containing
 *  backtrace location objects.
 *
 *  See Thread::Backtrace::Location for more information.
 *
 *  The optional _start_ parameter determines the number of initial stack
 *  entries to omit from the top of the stack.
 *
 *  A second optional +length+ parameter can be used to limit how many entries
 *  are returned from the stack.
 *
 *  Returns +nil+ if _start_ is greater than the size of
 *  current execution stack.
 *
 *  Optionally you can pass a range, which will return an array containing the
 *  entries within the specified range.
 */
static VALUE
rb_f_caller_locations(int argc, VALUE *argv)
{
    return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
}
예제 #23
0
파일: load.c 프로젝트: k-term/lesson
static void
rb_load_internal(VALUE fname, int wrap)
{
    rb_load_internal0(GET_THREAD(), fname, wrap);
}