Esempio n. 1
0
/**
 * Forks and runs the given application, waits for a maximum of timeout seconds for process to finish.
 *
 * @param argv The arguments values, the first one is the application path or name
 */
void bb_run_fork_wait(char** argv, int timeout) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    // Fork went ok, child process replace
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
      //sleep until process finishes or timeout reached
      int i = 0;
      while (bb_is_running(ret) && ((i < timeout) || (timeout == 0)) && dowait) {
        usleep(1000000);
        i++;
      }
      //make a single attempt to kill the process if timed out, without waiting
      if (bb_is_running(ret)) {
        bb_stop(ret);
      }
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return;
    }
  }
  return;
}
Esempio n. 2
0
/**
 * Runs a requested program if fallback mode was enabled
 * @param argv The program and param list to be executed
 * @return EXIT_FAILURE on failure and if fallback was disabled, -1 on failure
 * and if fallback was enabled and never on success
 */
static int run_fallback(char *argv[]) {
  if (bb_status.runmode == BB_RUN_APP && bb_config.fallback_start) {
    bb_log(LOG_WARNING, "The Bumblebee server was not available.\n");
    bb_run_exec(argv);
    bb_log(LOG_ERR, "Unable to start program in fallback mode.\n");
  }
  return EXIT_FAILURE;
}
Esempio n. 3
0
/**
 * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The
 * function then returns immediately.
 * stderr and stdout of the ran application is redirected to the parameter redirect.
 * stdin is redirected to /dev/null always.
 *
 * @param argv The arguments values, the first one is the program
 * @param ldpath The library path to be used if any (may be NULL)
 * @param redirect The file descriptor to redirect stdout/stderr to. Must be valid and open.
 * @return The childs process ID
 */
pid_t bb_run_fork_ld_redirect(char **argv, char *ldpath, int redirect) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    if (ldpath && *ldpath) {
      char *current_path = getenv("LD_LIBRARY_PATH");
      /* Fork went ok, set environment if necessary */
      if (current_path) {
        char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1);
        if (ldpath_new) {
          strcpy(ldpath_new, ldpath);
          strcat(ldpath_new, ":");
          strcat(ldpath_new, current_path);
          setenv("LD_LIBRARY_PATH", ldpath_new, 1);
          free(ldpath_new);
        } else {
          bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n");
        }
      } else {
        setenv("LD_LIBRARY_PATH", ldpath, 1);
      }
    }
    //open /dev/null for stdin redirect
    int devnull = open("/dev/null", O_RDWR);
    //fail silently on error, nothing we can do about it anyway...
    if (devnull >= 0){dup2(devnull, STDIN_FILENO);}
    //redirect stdout and stderr to the given filenum.
    dup2(redirect, STDOUT_FILENO);
    dup2(redirect, STDERR_FILENO);
    close(devnull);
    //ok, all ready, now actually execute
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return 0;
    }
  }
  return ret;
}
Esempio n. 4
0
/**
 * Forks and runs the given application and waits for the process to finish
 *
 * @param argv The arguments values, the first one is the program
 * @param detached non-zero if the std in/output must be redirected to /dev/null, zero otherwise
 * @return Exit code of the program (between 0 and 255) or -1 on failure
 */
int bb_run_fork(char **argv, int detached) {
  int exitcode = -1;

  check_handler();
  /* Fork and attempt to run given application */
  pid_t pid = fork();
  if (pid == 0) {
    /* child process after fork */
    if (detached) {
      bb_run_exec_detached(argv);
    } else {
      bb_run_exec(argv);
    }
  } else if (pid > 0) {
    /* parent process after fork */
    int status = 0;

    bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], pid);
    pidlist_add(pid);

    if (waitpid(pid, &status, 0) != -1) {
      if (WIFEXITED(status)) {
        /* program exited normally, return status */
        exitcode = WEXITSTATUS(status);
      } else if (WIFSIGNALED(status)) {
        /* program was terminated by a signal */
        exitcode = 128 + WTERMSIG(status);
      }
    } else {
      bb_log(LOG_ERR, "waitpid(%i) faild with %s\n", pid, strerror(errno));
    }
    pidlist_remove(pid);
  } else {
    /* Fork failed */
    bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
  }

  /* could not determine return value */
  return exitcode;
}
Esempio n. 5
0
/**
 * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The
 * function then returns immediately
 *
 * @param argv The arguments values, the first one is the program
 * @param ldpath The library path to be used if any (may be NULL)
 * @return The childs process ID
 */
pid_t bb_run_fork_ld(char **argv, char *ldpath) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    if (ldpath && *ldpath) {
      char *current_path = getenv("LD_LIBRARY_PATH");
      /* Fork went ok, set environment if necessary */
      if (current_path) {
        char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1);
        if (ldpath_new) {
          strcpy(ldpath_new, ldpath);
          strcat(ldpath_new, ":");
          strcat(ldpath_new, current_path);
          setenv("LD_LIBRARY_PATH", ldpath_new, 1);
          free(ldpath_new);
        } else {
          bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n");
        }
      } else {
        setenv("LD_LIBRARY_PATH", ldpath, 1);
      }
    }
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_INFO, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return 0;
    }
  }
  return ret;
}
Esempio n. 6
0
int main(int argc, char* argv[]) {

  /* Setup signal handling before anything else */
  signal(SIGHUP, handle_signal);
  signal(SIGTERM, handle_signal);
  signal(SIGINT, handle_signal);
  signal(SIGQUIT, handle_signal);

  /* Initializing configuration */
  init_config(argc, argv);
  
  /* set runmode depending on leftover arguments */
  if (optind >= argc) {
    bb_status.runmode = BB_RUN_STATUS;
  } else {
    bb_status.runmode = BB_RUN_APP;
  }

  bb_init_log();
  bb_log(LOG_DEBUG, "%s version %s starting...\n", bb_status.program_name, GITVERSION);

  /* Connect to listening daemon */
  bb_status.bb_socket = socketConnect(bb_config.socket_path, SOCK_NOBLOCK);
  if (bb_status.bb_socket < 0) {
    bb_log(LOG_ERR, "Could not connect to bumblebee daemon - is it running?\n");
    bb_closelog();
    return EXIT_FAILURE;
  }
  char buffer[BUFFER_SIZE];
  int r;

  /* Request status */
  if (bb_status.runmode == BB_RUN_STATUS) {
    r = snprintf(buffer, BUFFER_SIZE, "Status?");
    socketWrite(&bb_status.bb_socket, buffer, r);
    while (bb_status.bb_socket != -1) {
      r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
      if (r > 0) {
        printf("Bumblebee status: %*s\n", r, buffer);
        socketClose(&bb_status.bb_socket);
      }
    }
  }

  /* Run given application */
  if (bb_status.runmode == BB_RUN_APP) {
    int ranapp = 0;
    r = snprintf(buffer, BUFFER_SIZE, "Checking availability...");
    socketWrite(&bb_status.bb_socket, buffer, r);
    while (bb_status.bb_socket != -1) {
      r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
      if (r > 0) {
        bb_log(LOG_INFO, "Response: %*s\n", r, buffer);
        switch (buffer[0]) {
          case 'N': //No, run normally.
            socketClose(&bb_status.bb_socket);
            if (!bb_config.fallback_start){
              bb_log(LOG_ERR, "Cannot access secondary GPU. Aborting.\n");
            }
            break;
          case 'Y': //Yes, run through vglrun
            bb_log(LOG_INFO, "Running application through vglrun.\n");
            ranapp = 1;
            //run vglclient if any method other than proxy is used
            if (strncmp(bb_config.vgl_compress, "proxy", BUFFER_SIZE) != 0) {
              char * vglclient_args[] = {
                "vglclient",
                "-detach",
                0
              };
              bb_run_fork(vglclient_args);
            }
            char ** vglrun_args = malloc(sizeof (char *) * (9 + argc - optind));
            vglrun_args[0] = "vglrun";
            vglrun_args[1] = "-c";
            vglrun_args[2] = bb_config.vgl_compress;
            vglrun_args[3] = "-d";
            vglrun_args[4] = bb_config.x_display;
            vglrun_args[5] = "-ld";
            vglrun_args[6] = bb_config.ld_path;
            vglrun_args[7] = "--";
            for (r = 0; r < argc - optind; r++) {
              vglrun_args[8 + r] = argv[optind + r];
            }
            vglrun_args[8 + r] = 0;
            bb_run_fork_wait(vglrun_args);
            socketClose(&bb_status.bb_socket);
            break;
          default: //Something went wrong - output and exit.
            bb_log(LOG_ERR, "Problem: %*s\n", r, buffer);
            socketClose(&bb_status.bb_socket);
            break;
        }
      }
    }
    if (!ranapp && bb_config.fallback_start) {
      bb_log(LOG_WARNING, "Running application normally.\n");
      bb_run_exec(argv + optind);
    }
  }

  bb_closelog();
  bb_stop_all(); //stop any started processes that are left
  return (EXIT_SUCCESS);
}