RIO* Handle::as_rio(NativeMethodEnvironment* env) { IO* io_obj = c_as<IO>(object()); if(type_ != cRIO) { env->shared().capi_ds_lock().lock(); if(type_ != cRIO) { int fd = (int)io_obj->descriptor()->to_native(); env->shared().capi_ds_lock().unlock(); if(fd == -1) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); rb_raise(rb_eIOError, "%s (%d)", err, errno); } FILE* f = fdopen(fd, flags_modestr(io_obj->mode()->to_native())); if(!f) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); std::cerr << "Error convert fd (" << fd << ") to lowlevel IO: " << err << " (" << errno << ")" << std::endl; env->shared().capi_ds_lock().unlock(); rb_raise(rb_eTypeError, "unable to convert fd (%d) to lowlevel IO: %s (%d)", fd, err, errno); } RIO* rf = new RIO; rf->handle = as_value(); rf->fd = fd; rf->f = f; rf->f2 = NULL; rf->stdio_file = NULL; rf->finalize = NULL; // Disable all buffering so that it doesn't get out of sync with // the normal IO buffer. setvbuf(rf->f, 0, _IONBF, 0); type_ = cRIO; as_.rio = rf; } env->shared().capi_ds_lock().unlock(); } return as_.rio; }
void Thread::fork(STATE) { if(int error = start_thread(state, Thread::run)) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(error, buf, RBX_STRERROR_BUFSIZE); Exception::raise_thread_error(state, err); } }
Object* Thread::fork(STATE) { // If the thread is already alive or already ran, // we can't use it anymore. if(CBOOL(alive()) || !vm_) { return Primitives::failure(); } if(int error = start_thread(state, Thread::run)) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(error, buf, RBX_STRERROR_BUFSIZE); Exception::thread_error(state, err); } return cNil; }
void Fiber::start(STATE, Arguments& args) { state->vm()->thread()->fiber_value(state, args.as_array(state)); pthread_attr_t attrs; pthread_attr_init(&attrs); pthread_attr_setstacksize(&attrs, stack_size()->to_native()); pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); int status = pthread_create(&vm()->os_thread(), &attrs, Fiber::run, (void*)vm()); pthread_attr_destroy(&attrs); if(status != 0) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(status, buf, RBX_STRERROR_BUFSIZE); Exception::raise_fiber_error(state, err); } // Wait for Fiber thread to start up and pause. while(!vm()->suspended_p()) { ; // spin wait } }
void SignalHandler::setup_default_handlers(std::string path) { #ifndef RBX_WINDOWS report_path[0] = 0; // Calculate the report_path if(path.rfind("/") == std::string::npos) { if(char* home = getenv("HOME")) { snprintf(report_path, PATH_MAX, "%s/.rbx", home); pid_t pid = getpid(); bool use_dir = false; struct stat s; if(stat(report_path, &s) != 0) { if(mkdir(report_path, S_IRWXU) == 0) use_dir = true; } else if(S_ISDIR(s.st_mode)) { use_dir = true; } if(use_dir) { snprintf(report_path + strlen(report_path), PATH_MAX, "/%s_%d", path.c_str(), pid); } else { snprintf(report_path, PATH_MAX, "%s/.%s_%d", home, path.c_str(), pid); } } } if(!report_path[0]) { strncpy(report_path, path.c_str(), PATH_MAX-1); } // Test that we can actually use this path. int fd = open(report_path, O_RDONLY | O_CREAT, 0666); if(!fd) { char buf[RBX_STRERROR_BUFSIZE]; char* err = RBX_STRERROR(errno, buf, RBX_STRERROR_BUFSIZE); std::cerr << "Unable to use " << report_path << " for crash reports.\n"; std::cerr << "Unable to open path: " << err << "\n"; // Don't use the home dir path even, just use stderr report_path[0] = 0; } else { close(fd); unlink(report_path); } // Get the machine info. uname(&machine_info); struct sigaction action; action.sa_handler = null_func; action.sa_flags = 0; sigfillset(&action.sa_mask); sigaction(SIGVTALRM, &action, NULL); // Some extensions expect SIGALRM to be defined, because MRI does. // We'll just use a noop for it. action.sa_handler = null_func; sigaction(SIGALRM, &action, NULL); // Ignore sigpipe. action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); #ifdef USE_EXECINFO // If we have execinfo, setup some crash handlers if(!getenv("DISABLE_SEGV")) { action.sa_handler = segv_handler; sigaction(SIGSEGV, &action, NULL); sigaction(SIGBUS, &action, NULL); sigaction(SIGILL, &action, NULL); sigaction(SIGFPE, &action, NULL); sigaction(SIGABRT, &action, NULL); } #endif // USE_EXEC_INFO #else signal(SIGTERM, quit_handler); #endif // ifndef RBX_WINDOWS }