예제 #1
0
파일: io.cpp 프로젝트: Azzurrio/rubinius
    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;
    }
예제 #2
0
 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);
   }
 }
예제 #3
0
파일: thread.cpp 프로젝트: Red54/rubinius
  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;
  }
예제 #4
0
파일: fiber.cpp 프로젝트: Justme0/rubinius
  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
    }
  }
예제 #5
0
  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
  }