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; }
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); }
/* * 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; }
int rb_w32_sleep(unsigned long msec) { return w32_wait_events(0, 0, msec, GET_THREAD()); }
void rb_set_safe_level_force(int safe) { GET_THREAD()->safe_level = safe; }
VALUE rb_make_backtrace(void) { return rb_vm_backtrace_str_ary(GET_THREAD(), 0, 0); }
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); }
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); } }
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 }
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, ®isters[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 (®isters[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 }
/** * 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 }
rb_thread_t *GET_THREAD2(void) { ruby_current_thread = ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current())); return GET_THREAD(); }
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; }
/* * 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(); }
/** * 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); } }
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); }
void rb_vmdebug_stack_dump_raw_current(void) { rb_thread_t *th = GET_THREAD(); rb_vmdebug_stack_dump_raw(th, th->cfp); }
int rb_safe_level(void) { return GET_THREAD()->safe_level; }
static void gvl_atfork(rb_vm_t *vm) { gvl_init(vm); gvl_acquire(vm, GET_THREAD()); }
VALUE rb_vm_backtrace_object(void) { return backtrace_object(GET_THREAD()); }
int rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout) { return w32_wait_events(events, num, timeout, GET_THREAD()); }
/* * 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); }
static void rb_load_internal(VALUE fname, int wrap) { rb_load_internal0(GET_THREAD(), fname, wrap); }