Beispiel #1
0
void 
check_jobs(std::string &alias, std::map<pid_t, std::string> & running_processes, const int max_concurrent_jobs)
{
    airport::Mongo mongoDB;
    mongo::DBClientConnection mongoConnection;
    mongoDB.connect(&mongoConnection);
    mongoConnection.ensureIndex(MONGO_DISPATCHER_COLLECTION, mongo::fromjson("{servername:1, started_datetime:1, completed_datetime:1, archived:1}"));
    std::auto_ptr<mongo::DBClientCursor> cursor = mongoConnection.query( MONGO_DISPATCHER_COLLECTION, mongo::QUERY("servername"<<alias<<"started_datetime"<<0<<"completed_datetime"<<0<<"archived"<<false) );
    while(cursor->more())
    {
        mongo::BSONObj b = cursor->next();
        if (running_processes.size() >= max_concurrent_jobs)
            continue;
        std::string rulename = b.getStringField("rulename");
        std::string rulecontent = b.getStringField("rule");
        std::string rule_path = airport::DATA_PATH + "rules/" + rulename;
        std::ofstream rulefile (rule_path.c_str());
        rulefile << rulecontent;
        rulefile.close();
        pid_t pid = subprocess( rulename, alias );
        if (pid > 0)
        {
            running_processes.insert(std::map<pid_t, std::string>::value_type(pid, rulename) );
            mongo::BSONElement e;
            bool getId = b.getObjectID (e);
            if (getId)
            {
                mongo::OID oid = e.__oid();
                mongoConnection.update( MONGO_DISPATCHER_COLLECTION, BSON("_id"<<oid) , BSON("$set"<<BSON("started_datetime"<<(long long int)time(NULL))) );
            }
        }
        sleep(2);
    }
}
Beispiel #2
0
// TODO(jmlvanre): Consider removing default argument for
// `parent_hooks` to force the caller to think about setting them.
inline Try<Subprocess> subprocess(
    const std::string& command,
    const Subprocess::IO& in = Subprocess::FD(STDIN_FILENO),
    const Subprocess::IO& out = Subprocess::FD(STDOUT_FILENO),
    const Subprocess::IO& err = Subprocess::FD(STDERR_FILENO),
    const Option<std::map<std::string, std::string>>& environment = None(),
    const Option<lambda::function<int()>>& setup = None(),
    const Option<lambda::function<
        pid_t(const lambda::function<int()>&)>>& clone = None(),
    const std::vector<Subprocess::Hook>& parent_hooks =
      Subprocess::Hook::None())
{
  std::vector<std::string> argv = {"sh", "-c", command};

  return subprocess(
      "sh",
      argv,
      in,
      out,
      err,
      None(),
      environment,
      setup,
      clone,
      parent_hooks);
}
Try<Nothing> MemoryTestHelper::spawn()
{
  if (s.isSome()) {
    return Error("A subprocess has been spawned already");
  }

  vector<string> argv;
  argv.push_back("test-helper");
  argv.push_back(MemoryTestHelper::NAME);

  Try<Subprocess> process = subprocess(
      getTestHelperPath("test-helper"),
      argv,
      Subprocess::PIPE(),
      Subprocess::PIPE(),
      Subprocess::FD(STDERR_FILENO));

  if (process.isError()) {
    return Error("Failed to spawn a subprocess: " + process.error());
  }

  s = process.get();

  // Wait for the child to inform it has started before returning.
  // Otherwise, the user might set the memory limit too earlier, and
  // cause the child oom-killed because 'ld' could use a lot of
  // memory.
  Result<string> read = os::read(s->out().get(), sizeof(STARTED));
  if (!read.isSome() || read.get() != string(sizeof(STARTED), STARTED)) {
    cleanup();
    return Error("Failed to sync with the subprocess");
  }

  return Nothing();
}
Beispiel #4
0
  Try<Subprocess> run(
      const string& _command,
      const Option<string>& rootfs = None())
  {
    slave::MesosContainerizerLaunch::Flags launchFlags;

    CommandInfo command;
    command.set_value(_command);

    launchFlags.command = JSON::Protobuf(command);
    launchFlags.directory = "/tmp";
    launchFlags.pipe_read = open("/dev/zero", O_RDONLY);
    launchFlags.pipe_write = open("/dev/null", O_WRONLY);
    launchFlags.rootfs = rootfs;

    vector<string> argv(2);
    argv[0] = "mesos-containerizer";
    argv[1] = slave::MesosContainerizerLaunch::NAME;

    Try<Subprocess> s = subprocess(
        path::join(tests::flags.build_dir, "src", "mesos-containerizer"),
        argv,
        Subprocess::PATH("/dev/null"),
        Subprocess::FD(STDOUT_FILENO),
        Subprocess::FD(STDERR_FILENO),
        launchFlags,
        None(),
        None(),
        lambda::bind(&clone, lambda::_1));

    close(launchFlags.pipe_read.get());
    close(launchFlags.pipe_write.get());

    return s;
  }
Beispiel #5
0
static void expect2(const char *code, const char *type, const char *output)
{
	int ret;
	struct context context = { code, type, output };

	ret = subprocess(&context);
	if (ret != EXIT_SUCCESS)
		exit(1);
}
Beispiel #6
0
Future<Nothing> untar(const string& file, const string& directory)
{
  const vector<string> argv = {
    "tar",
    "-C",
    directory,
    "-x",
    "-f",
    file
  };

  Try<Subprocess> s = subprocess(
      "tar",
      argv,
      Subprocess::PATH("/dev/null"),
      Subprocess::PATH("/dev/null"),
      Subprocess::PIPE());

  if (s.isError()) {
    return Failure("Failed to execute the subprocess: " + s.error());
  }

  return await(
      s.get().status(),
      process::io::read(s.get().err().get()))
    .then([](const tuple<
        Future<Option<int>>,
        Future<string>>& t) -> Future<Nothing> {
      Future<Option<int>> status = std::get<0>(t);
      if (!status.isReady()) {
        return Failure(
          "Failed to get the exit status of the subprocess: " +
          (status.isFailed() ? status.failure() : "discarded"));
      }

      Future<string> error = std::get<1>(t);
      if (!error.isReady()) {
        return Failure(
          "Failed to read stderr from the subprocess: " +
          (error.isFailed() ? error.failure() : "discarded"));
      }

      if (status->isNone()) {
        return Failure("Failed to reap the subprocess");
      }

      if (status->get() != 0) {
        return Failure(
            "Unexpected result from the subprocess: " +
            WSTRINGIFY(status->get()) +
            ", stderr='" + error.get() + "'");
      }

      return Nothing();
    });
}
Beispiel #7
0
int main(int argc, char **argv) {
  char buffer[BUFFER + 1], *cursor, *separator;
  int sock;
  ssize_t length;
  struct sockaddr_nl addr;

  progname = argv[0];
  if (argc > 1)
    subprocess(argv + 1);

  memset(&addr, 0, sizeof(addr));
  addr.nl_family = AF_NETLINK;
  addr.nl_pid = getpid();
  addr.nl_groups = 1;

  if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0)
    error(EXIT_FAILURE, errno, "socket");

  if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
    error(EXIT_FAILURE, errno, "bind");

  while (1) {
    if ((length = recv(sock, &buffer, sizeof(buffer) - 1, 0)) < 0) {
      if (errno != EAGAIN && errno != EINTR)
        error(EXIT_FAILURE, errno, "recv");
      continue;
    }

    /* Null-terminate the uevent and replace stray newlines with spaces. */
    buffer[length] = 0;
    for (cursor = buffer; cursor < buffer + length; cursor++)
      if (*cursor == '\n')
        *cursor = ' ';

    if (strlen(buffer) >= length - 1) {
      /* No properties; fake a simple environment based on the header. */
      if ((cursor = strchr(buffer, '@'))) {
        *cursor++ = 0;
        printf("ACTION %s\n", buffer);
        printf("DEVPATH %s\n", cursor);
      }
    } else {
      /* Ignore header as properties will include ACTION and DEVPATH. */
      cursor = buffer;
      while (cursor += strlen(cursor) + 1, cursor < buffer + length) {
        if ((separator = strchr(cursor, '=')))
          *separator = ' ';
        puts(cursor);
      }
    }
    putchar('\n');
    fflush(stdout);
  }

  return EXIT_FAILURE;
}
Beispiel #8
0
int main (int argc, char* argv[])
{
    int cmd_start_index;
    int i;
    pid_t pid, hardlimit_monitor;

    init_default_limits ();
    cmd_start_index = parse_args (argc, argv);

    /* be safe on the timehard! */
    if (limit_timehard < 1 + (int) ceil (limit_time))
        limit_timehard = 1 + (int) ceil (limit_time);

    /* close inherited file descriptors. Is there a better way? */
    for (i = 3; i < (1<<16); i++)
        close (i);

    pid = fork();
    if (pid==0) {
        return subprocess (argc - cmd_start_index, argv + cmd_start_index);
    }

    hardlimit_monitor = fork ();
    if (hardlimit_monitor == 0) {
        sleep (6*limit_timehard);
        /* if I reached here, then the main process is still running,
         * upto some race condition possibilitiy */
        //fprintf (stderr, "Severe hardlimit (%d) reached. Possibly \
        malicious, or overloaded system.\n", 6*limit_timehard);
        kill (pid, 9);
        return 0;
    }

        int status;
        struct rusage usage ;

        /*
        * Correctness: Pid dies on its own or, hardlimit_monitor process
        * kills it. In both cases, this works, except perhaps the Pid
        * process can be called for kill twice.
        */
        wait4(pid,&status, 0, &usage); //Wait for child to terminate
        kill (hardlimit_monitor, 9);
        waitpid (hardlimit_monitor, NULL, 0);

        // lets output the limits.
        fflush(stderr) ; /* ordering of output of child and parent should be right */



        double usertime = (float) (usage.ru_utime.tv_sec) + ((float) usage.ru_utime.tv_usec)/1000000 ;
//fprintf(stderr, "Usertime:
        %lf\n", usertime);
Beispiel #9
0
Future<Nothing> CurlFetcherPlugin::fetch(
    const URI& uri,
    const string& directory)
{
  // TODO(jieyu): Validate the given URI.

  if (!uri.has_path()) {
    return Failure("URI path is not specified");
  }

  if (!os::exists(directory)) {
    Try<Nothing> mkdir = os::mkdir(directory);
    if (mkdir.isError()) {
      return Failure(
          "Failed to create directory '" +
          directory + "': " + mkdir.error());
    }
  }

  // TODO(jieyu): Allow user to specify the name of the output file.
  const string output = path::join(directory, Path(uri.path()).basename());

  const vector<string> argv = {
    "curl",
    "-s",                 // Don’t show progress meter or error messages.
    "-S",                 // Makes curl show an error message if it fails.
    "-L",                 // Follow HTTP 3xx redirects.
    "-w", "%{http_code}", // Display HTTP response code on stdout.
    "-o", output,         // Write output to the file.
    strings::trim(stringify(uri))
  };

  Try<Subprocess> s = subprocess(
      "curl",
      argv,
      Subprocess::PATH("/dev/null"),
      Subprocess::PIPE(),
      Subprocess::PIPE());

  if (s.isError()) {
    return Failure("Failed to exec the curl subprocess: " + s.error());
  }

  return await(
      s.get().status(),
      io::read(s.get().out().get()),
      io::read(s.get().err().get()))
    .then(_fetch);
}
Beispiel #10
0
int main(int argc, char** argv)
{
	//

	//pipe
	int fd[2];
	int result = pipe(fd);
	if (result == -1) {
		perror("pipe error!");
		exit(1);
	}
	//fork
	pid_t pid = fork();
	if (pid == 0) {
		//子进程
		close(fd[1]);//关闭写通道
		subprocess(fd[0]);//监督读取通道
	} else if (pid > 0){
		//主进程
		close(fd[0]);//关闭读通道,使用写通道
	} else {
		//fork错误
		char* errinfo = strerror(errno);
		int length = strlen(errinfo)+7;
		char* err = malloc(length);
		snprintf(err, length, "FORK: %s", errinfo);
		perror(err);
		free(err);
		exit(1);
	}

	char str[512];
	int done = 1;
	do {
		scanf("%s", str);
		if (!strcmp(str, "quit")) {
			done = 0;
			write(fd[1], str, strlen(str)+1);
			wait(NULL);
		} else {
			//向子进程写入命令
			write(fd[1], str, strlen(str)+1);
		}
	} while (done);
	
	close(fd[1]);//关闭写通道

	return 0;
}
Beispiel #11
0
/* Process one line of input from virtual channel */
static BOOL
lspci_process_line(const char *line, void *data)
{
	char *lspci_command[5] = { "lspci", "-m", "-n", "-v", NULL };

	if (!strcmp(line, "LSPCI"))
	{
		memset(&current_device, 0, sizeof(current_device));
		subprocess(lspci_command, handle_child_line, NULL);
		/* Send single dot to indicate end of enumeration */
		lspci_send(".\n");
	}
	else
	{
		error("lspci protocol error: Invalid line '%s'\n", line);
	}
	return True;
}
Beispiel #12
0
  // Launch 'ping' using the given capabilities and user.
  Try<Subprocess> ping(
      const Set<Capability>& capabilities,
      const Option<string>& user = None())
  {
    CapabilitiesTestHelper helper;

    helper.flags.user = user;
    helper.flags.capabilities = capabilities::convert(capabilities);

    vector<string> argv = {
      "test-helper",
      CapabilitiesTestHelper::NAME
    };

    return subprocess(
        getTestHelperPath("test-helper"),
        argv,
        Subprocess::FD(STDIN_FILENO),
        Subprocess::FD(STDOUT_FILENO),
        Subprocess::FD(STDERR_FILENO),
        NO_SETSID,
        &helper.flags);
  }
Beispiel #13
0
Future<Nothing> untar(const string& file, const string& directory)
{
  const vector<string> argv = {
    "tar",
    "-C",
    directory,
    "-x",
    "-f",
    file
  };

  Try<Subprocess> s = subprocess(
      "tar",
      argv,
      Subprocess::PATH("/dev/null"),
      Subprocess::PATH("/dev/null"),
      Subprocess::PIPE());

  if (s.isError()) {
    return Failure(
        "Failed to create untar subprocess for file '" +
        file + "': " + s.error());
  }

  Owned<Promise<Nothing>> promise(new Promise<Nothing>());
  s.get().status()
    .onAny([s, file, promise](const Future<Option<int>>& future) {
      if (!future.isReady()) {
        promise->fail(
            "Failed to launch untar subprocess for file '" + file
            + "': " +
            (future.isFailed() ? future.failure() : "future discarded"));

        return;
      }

      if (future.get().isNone()) {
        promise->fail(
            "Failed to get status for untar subprocess for file '" +
            file + "'");

        return;
      }

      int status = future.get().get();

      if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        const string errorMessage =
          "Failed to run ntar process for file '" + file + "' (exit code: " +
          WSTRINGIFY(status) + ")";

        // Read stderr from the process(if any) to add to the failure report.
        process::io::read(s.get().err().get())
          .onAny([file, promise, errorMessage](const Future<string>& future) {
            if (!future.isReady()) {
              LOG(WARNING) << "Failed to read stderr from untar process for"
                           << "file: '" << file << "': "
                           << (future.isFailed() ? future.failure()
                              : "future discarded");

              promise->fail(errorMessage);
            } else {
              promise->fail(errorMessage + ": " + future.get());
            }
          });

        return;
      }

      promise->set(Nothing());
    });

    return promise->future();
}
Beispiel #14
0
/*
 * Checks whether key is allowed in output of command.
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
user_key_command_allowed2(struct passwd *user_pw, Key *key)
{
	FILE *f = NULL;
	int r, ok, found_key = 0;
	struct passwd *pw;
	int i, uid_swapped = 0, ac = 0;
	pid_t pid;
	char *username = NULL, *key_fp = NULL, *keytext = NULL;
	char *tmp, *command = NULL, **av = NULL;
	void (*osigchld)(int);

	if (options.authorized_keys_command == NULL)
		return 0;
	if (options.authorized_keys_command_user == NULL) {
		error("No user for AuthorizedKeysCommand specified, skipping");
		return 0;
	}

	/*
	 * NB. all returns later this function should go via "out" to
	 * ensure the original SIGCHLD handler is restored properly.
	 */
	osigchld = signal(SIGCHLD, SIG_DFL);

	/* Prepare and verify the user for the command */
	username = percent_expand(options.authorized_keys_command_user,
	    "u", user_pw->pw_name, (char *)NULL);
	pw = getpwnam(username);
	if (pw == NULL) {
		error("AuthorizedKeysCommandUser \"%s\" not found: %s",
		    username, strerror(errno));
		goto out;
	}

	/* Prepare AuthorizedKeysCommand */
	if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash,
	    SSH_FP_DEFAULT)) == NULL) {
		error("%s: sshkey_fingerprint failed", __func__);
		goto out;
	}
	if ((r = sshkey_to_base64(key, &keytext)) != 0) {
		error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
		goto out;
	}

	/* Turn the command into an argument vector */
	if (split_argv(options.authorized_keys_command, &ac, &av) != 0) {
		error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
		    command);
		goto out;
	}
	if (ac == 0) {
		error("AuthorizedKeysCommand \"%s\" yielded no arguments",
		    command);
		goto out;
	}
	for (i = 1; i < ac; i++) {
		tmp = percent_expand(av[i],
		    "u", user_pw->pw_name,
		    "h", user_pw->pw_dir,
		    "t", sshkey_ssh_name(key),
		    "f", key_fp,
		    "k", keytext,
		    (char *)NULL);
		if (tmp == NULL)
			fatal("%s: percent_expand failed", __func__);
		free(av[i]);
		av[i] = tmp;
	}
	/* Prepare a printable command for logs, etc. */
	command = assemble_argv(ac, av);

	/*
	 * If AuthorizedKeysCommand was run without arguments
	 * then fall back to the old behaviour of passing the
	 * target username as a single argument.
	 */
	if (ac == 1) {
		av = xreallocarray(av, ac + 2, sizeof(*av));
		av[1] = xstrdup(user_pw->pw_name);
		av[2] = NULL;
		/* Fix up command too, since it is used in log messages */
		free(command);
		xasprintf(&command, "%s %s", av[0], av[1]);
	}

	if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
	    ac, av, &f)) == 0)
		goto out;

	uid_swapped = 1;
	temporarily_use_uid(pw);

	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);

	fclose(f);
	f = NULL;

	if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
		goto out;

	/* Read completed successfully */
	found_key = ok;
 out:
	if (f != NULL)
		fclose(f);
	signal(SIGCHLD, osigchld);
	for (i = 0; i < ac; i++)
		free(av[i]);
	free(av);
	if (uid_swapped)
		restore_uid();
	free(command);
	free(username);
	free(key_fp);
	free(keytext);
	return found_key;
}
Beispiel #15
0
/*
 * Checks whether principal is allowed in output of command.
 * returns 1 if the principal is allowed or 0 otherwise.
 */
static int
match_principals_command(struct passwd *user_pw, const struct sshkey *key)
{
	const struct sshkey_cert *cert = key->cert;
	FILE *f = NULL;
	int r, ok, found_principal = 0;
	struct passwd *pw;
	int i, ac = 0, uid_swapped = 0;
	pid_t pid;
	char *tmp, *username = NULL, *command = NULL, **av = NULL;
	char *ca_fp = NULL, *key_fp = NULL, *catext = NULL, *keytext = NULL;
	char serial_s[16];
	void (*osigchld)(int);

	if (options.authorized_principals_command == NULL)
		return 0;
	if (options.authorized_principals_command_user == NULL) {
		error("No user for AuthorizedPrincipalsCommand specified, "
		    "skipping");
		return 0;
	}

	/*
	 * NB. all returns later this function should go via "out" to
	 * ensure the original SIGCHLD handler is restored properly.
	 */
	osigchld = signal(SIGCHLD, SIG_DFL);

	/* Prepare and verify the user for the command */
	username = percent_expand(options.authorized_principals_command_user,
	    "u", user_pw->pw_name, (char *)NULL);
	pw = getpwnam(username);
	if (pw == NULL) {
		error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
		    username, strerror(errno));
		goto out;
	}

	/* Turn the command into an argument vector */
	if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
		error("AuthorizedPrincipalsCommand \"%s\" contains "
		    "invalid quotes", command);
		goto out;
	}
	if (ac == 0) {
		error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
		    command);
		goto out;
	}
	if ((ca_fp = sshkey_fingerprint(cert->signature_key,
	    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
		error("%s: sshkey_fingerprint failed", __func__);
		goto out;
	}
	if ((key_fp = sshkey_fingerprint(key,
	    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
		error("%s: sshkey_fingerprint failed", __func__);
		goto out;
	}
	if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) {
		error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
		goto out;
	}
	if ((r = sshkey_to_base64(key, &keytext)) != 0) {
		error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
		goto out;
	}
	snprintf(serial_s, sizeof(serial_s), "%llu",
	    (unsigned long long)cert->serial);
	for (i = 1; i < ac; i++) {
		tmp = percent_expand(av[i],
		    "u", user_pw->pw_name,
		    "h", user_pw->pw_dir,
		    "t", sshkey_ssh_name(key),
		    "T", sshkey_ssh_name(cert->signature_key),
		    "f", key_fp,
		    "F", ca_fp,
		    "k", keytext,
		    "K", catext,
		    "i", cert->key_id,
		    "s", serial_s,
		    (char *)NULL);
		if (tmp == NULL)
			fatal("%s: percent_expand failed", __func__);
		free(av[i]);
		av[i] = tmp;
	}
	/* Prepare a printable command for logs, etc. */
	command = assemble_argv(ac, av);

	if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
	    ac, av, &f)) == 0)
		goto out;

	uid_swapped = 1;
	temporarily_use_uid(pw);

	ok = process_principals(f, NULL, pw, cert);

	fclose(f);
	f = NULL;

	if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
		goto out;

	/* Read completed successfully */
	found_principal = ok;
 out:
	if (f != NULL)
		fclose(f);
	signal(SIGCHLD, osigchld);
	for (i = 0; i < ac; i++)
		free(av[i]);
	free(av);
	if (uid_swapped)
		restore_uid();
	free(command);
	free(username);
	free(ca_fp);
	free(key_fp);
	free(catext);
	free(keytext);
	return found_principal;
}
Beispiel #16
0
pid_t launchTaskPosix(
    const CommandInfo& command,
    const string& launcherDir,
    const Environment& environment,
    const Option<string>& user,
    const Option<string>& rootfs,
    const Option<string>& sandboxDirectory,
    const Option<string>& workingDirectory,
    const Option<CapabilityInfo>& capabilities)
{
  // Prepare the flags to pass to the launch process.
  MesosContainerizerLaunch::Flags launchFlags;

  ContainerLaunchInfo launchInfo;
  launchInfo.mutable_command()->CopyFrom(command);

  if (rootfs.isSome()) {
    // The command executor is responsible for chrooting into the
    // root filesystem and changing the user before exec-ing the
    // user process.
#ifdef __linux__
    if (geteuid() != 0) {
      ABORT("The command executor requires root with rootfs");
    }

    // Ensure that mount namespace of the executor is not affected by
    // changes in its task's namespace induced by calling `pivot_root`
    // as part of the task setup in mesos-containerizer binary.
    launchFlags.unshare_namespace_mnt = true;
#else
    ABORT("Not expecting root volume with non-linux platform");
#endif // __linux__

    launchInfo.set_rootfs(rootfs.get());

    CHECK_SOME(sandboxDirectory);

    launchInfo.set_working_directory(workingDirectory.isSome()
      ? workingDirectory.get()
      : sandboxDirectory.get());

    // TODO(jieyu): If the task has a rootfs, the executor itself will
    // be running as root. Its sandbox is owned by root as well. In
    // order for the task to be able to access to its sandbox, we need
    // to make sure the owner of the sandbox is 'user'. However, this
    // is still a workaround. The owner of the files downloaded by the
    // fetcher is still not correct (i.e., root).
    if (user.isSome()) {
      // NOTE: We only chown the sandbox directory (non-recursively).
      Try<Nothing> chown = os::chown(user.get(), os::getcwd(), false);
      if (chown.isError()) {
        ABORT("Failed to chown sandbox to user " +
              user.get() + ": " + chown.error());
      }
    }
  }

  launchInfo.mutable_environment()->CopyFrom(environment);

  if (user.isSome()) {
    launchInfo.set_user(user.get());
  }

  if (capabilities.isSome()) {
    launchInfo.mutable_capabilities()->CopyFrom(capabilities.get());
  }

  launchFlags.launch_info = JSON::protobuf(launchInfo);

  string commandString = strings::format(
      "%s %s %s",
      path::join(launcherDir, MESOS_CONTAINERIZER),
      MesosContainerizerLaunch::NAME,
      stringify(launchFlags)).get();

  // Fork the child using launcher.
  vector<string> argv(2);
  argv[0] = MESOS_CONTAINERIZER;
  argv[1] = MesosContainerizerLaunch::NAME;

  Try<Subprocess> s = subprocess(
      path::join(launcherDir, MESOS_CONTAINERIZER),
      argv,
      Subprocess::FD(STDIN_FILENO),
      Subprocess::FD(STDOUT_FILENO),
      Subprocess::FD(STDERR_FILENO),
      &launchFlags,
      None(),
      None(),
      {},
      {Subprocess::ChildHook::SETSID()});

  if (s.isError()) {
    ABORT("Failed to launch '" + commandString + "': " + s.error());
  }

  cout << commandString << endl;

  return s->pid();
}
Beispiel #17
0
/*
 * Checks whether principal is allowed in output of command.
 * returns 1 if the principal is allowed or 0 otherwise.
 */
static int
match_principals_command(struct passwd *user_pw, struct sshkey_cert *cert)
{
	FILE *f = NULL;
	int ok, found_principal = 0;
	struct passwd *pw;
	int i, ac = 0, uid_swapped = 0;
	pid_t pid;
	char *tmp, *username = NULL, *command = NULL, **av = NULL;
	void (*osigchld)(int);

	if (options.authorized_principals_command == NULL)
		return 0;
	if (options.authorized_principals_command_user == NULL) {
		error("No user for AuthorizedPrincipalsCommand specified, "
		    "skipping");
		return 0;
	}

	/*
	 * NB. all returns later this function should go via "out" to
	 * ensure the original SIGCHLD handler is restored properly.
	 */
#ifndef WIN32_FIXME
// PRAGMA:TODO
	osigchld = signal(SIGCHLD, SIG_DFL);
#endif

	/* Prepare and verify the user for the command */
	username = percent_expand(options.authorized_principals_command_user,
	    "u", user_pw->pw_name, (char *)NULL);
	pw = getpwnam(username);
	if (pw == NULL) {
		error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
		    username, strerror(errno));
		goto out;
	}

	/* Turn the command into an argument vector */
	if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
		error("AuthorizedPrincipalsCommand \"%s\" contains "
		    "invalid quotes", command);
		goto out;
	}
	if (ac == 0) {
		error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
		    command);
		goto out;
	}
	for (i = 1; i < ac; i++) {
		tmp = percent_expand(av[i],
		    "u", user_pw->pw_name,
		    "h", user_pw->pw_dir,
		    (char *)NULL);
		if (tmp == NULL)
			fatal("%s: percent_expand failed", __func__);
		free(av[i]);
		av[i] = tmp;
	}
	/* Prepare a printable command for logs, etc. */
	command = assemble_argv(ac, av);

	if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
	    ac, av, &f)) == 0)
		goto out;

	uid_swapped = 1;
	temporarily_use_uid(pw);

	ok = process_principals(f, NULL, pw, cert);

	if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
		goto out;

	/* Read completed successfully */
	found_principal = ok;
 out:
	if (f != NULL)
		fclose(f);
	signal(SIGCHLD, osigchld);
	for (i = 0; i < ac; i++)
		free(av[i]);
	free(av);
	if (uid_swapped)
		restore_uid();
	free(command);
	free(username);
	return found_principal;
}
Beispiel #18
0
Future<Nothing> CopyFetcherPlugin::fetch(
    const URI& uri,
    const string& directory) const
{
  // TODO(jojy): Validate the given URI.

  if (!uri.has_path()) {
    return Failure("URI path is not specified");
  }

  // TODO(jojy): Verify that the path is a file.

  Try<Nothing> mkdir = os::mkdir(directory);
  if (mkdir.isError()) {
    return Failure(
        "Failed to create directory '" +
        directory + "': " + mkdir.error());
  }

  VLOG(1) << "Copying '" << uri.path() << "' to '" << directory << "'";

  const vector<string> argv = {"cp", "-a", uri.path(), directory};

  Try<Subprocess> s = subprocess(
      "cp",
      argv,
      Subprocess::PATH(os::DEV_NULL),
      Subprocess::PIPE(),
      Subprocess::PIPE());

  if (s.isError()) {
    return Failure("Failed to exec the copy subprocess: " + s.error());
  }

  return await(
      s.get().status(),
      io::read(s.get().out().get()),
      io::read(s.get().err().get()))
    .then([](const tuple<
        Future<Option<int>>,
        Future<string>,
        Future<string>>& t) -> Future<Nothing> {
      Future<Option<int>> status = std::get<0>(t);
      if (!status.isReady()) {
        return Failure(
            "Failed to get the exit status of the copy subprocess: " +
            (status.isFailed() ? status.failure() : "discarded"));
      }

      if (status->isNone()) {
        return Failure("Failed to reap the copy subprocess");
      }

      if (status->get() != 0) {
        Future<string> error = std::get<2>(t);
        if (!error.isReady()) {
          return Failure(
              "Failed to perform 'copy'. Reading stderr failed: " +
              (error.isFailed() ? error.failure() : "discarded"));
        }

        return Failure("Failed to perform 'copy': " + error.get());
      }

      return Nothing();
    });
}
Beispiel #19
0
Future<Nothing> CurlFetcherPlugin::fetch(
    const URI& uri,
    const string& directory)
{
  // TODO(jieyu): Validate the given URI.

  if (!uri.has_path()) {
    return Failure("URI path is not specified");
  }

  Try<Nothing> mkdir = os::mkdir(directory);
  if (mkdir.isError()) {
    return Failure(
        "Failed to create directory '" +
        directory + "': " + mkdir.error());
  }

  // TODO(jieyu): Allow user to specify the name of the output file.
  const string output = path::join(directory, Path(uri.path()).basename());

  const vector<string> argv = {
    "curl",
    "-s",                 // Don’t show progress meter or error messages.
    "-S",                 // Makes curl show an error message if it fails.
    "-L",                 // Follow HTTP 3xx redirects.
    "-w", "%{http_code}", // Display HTTP response code on stdout.
    "-o", output,         // Write output to the file.
    strings::trim(stringify(uri))
  };

  Try<Subprocess> s = subprocess(
      "curl",
      argv,
      Subprocess::PATH("/dev/null"),
      Subprocess::PIPE(),
      Subprocess::PIPE());

  if (s.isError()) {
    return Failure("Failed to exec the curl subprocess: " + s.error());
  }

  return await(
      s.get().status(),
      io::read(s.get().out().get()),
      io::read(s.get().err().get()))
    .then([](const tuple<
        Future<Option<int>>,
        Future<string>,
        Future<string>>& t) -> Future<Nothing> {
      Future<Option<int>> status = std::get<0>(t);
      if (!status.isReady()) {
        return Failure(
            "Failed to get the exit status of the curl subprocess: " +
            (status.isFailed() ? status.failure() : "discarded"));
      }

      if (status->isNone()) {
        return Failure("Failed to reap the curl subprocess");
      }

      if (status->get() != 0) {
        Future<string> error = std::get<2>(t);
        if (!error.isReady()) {
          return Failure(
              "Failed to perform 'curl'. Reading stderr failed: " +
              (error.isFailed() ? error.failure() : "discarded"));
        }

        return Failure("Failed to perform 'curl': " + error.get());
      }

      Future<string> output = std::get<1>(t);
      if (!output.isReady()) {
        return Failure(
            "Failed to read stdout from 'curl': " +
            (output.isFailed() ? output.failure() : "discarded"));
      }

      // Parse the output and get the HTTP response code.
      Try<int> code = numify<int>(output.get());
      if (code.isError()) {
        return Failure("Unexpected output from 'curl': " + output.get());
      }

      if (code.get() != http::Status::OK) {
        return Failure(
            "Unexpected HTTP response code: " +
            http::Status::string(code.get()));
      }

      return Nothing();
    });
}
Beispiel #20
0
int main(int argc, char** argv)
{
  utils::mpi_world mpi_world(argc, argv);
  
  const int mpi_rank = MPI::COMM_WORLD.Get_rank();
  const int mpi_size = MPI::COMM_WORLD.Get_size();
  
  try {
    if (getoptions(argc, argv) != 0) 
      return 1;

    if (command.empty())
      throw std::runtime_error("no command?");

    typedef MapReduce map_reduce_type;
      
    typedef map_reduce_type::id_type         id_type;
    typedef map_reduce_type::value_type      value_type;
    typedef map_reduce_type::queue_type      queue_type;
    typedef map_reduce_type::queue_id_type   queue_id_type;
    typedef map_reduce_type::subprocess_type subprocess_type;

    typedef Mapper  mapper_type;
    typedef Reducer reducer_type;
    
    typedef Consumer consumer_type;
    typedef Merger   merger_type;
    
    if (mpi_rank == 0) {
      subprocess_type subprocess(command);
      
      queue_type    queue_is(mpi_size);
      queue_type    queue_send(1);
      queue_id_type queue_id;
      queue_type    queue_recv;
      
      const bool flush_output = (output_file == "-"
				 || (boost::filesystem::exists(output_file)
				     && ! boost::filesystem::is_regular_file(output_file)));
      
      utils::compress_istream is(input_file, 1024 * 1024);
      utils::compress_ostream os(output_file, 1024 * 1024 * (! flush_output));

      boost::thread consumer(consumer_type(queue_is, is));
      boost::thread merger(merger_type(queue_recv, os, mpi_size));

      boost::thread mapper(mapper_type(queue_send, queue_id, subprocess));
      boost::thread reducer(reducer_type(queue_recv, queue_id, subprocess));
      
      typedef utils::mpi_ostream        ostream_type;
      typedef utils::mpi_istream_simple istream_type;

      typedef boost::shared_ptr<ostream_type> ostream_ptr_type;
      typedef boost::shared_ptr<istream_type> istream_ptr_type;
      
      typedef std::vector<ostream_ptr_type, std::allocator<ostream_ptr_type> > ostream_ptr_set_type;
      typedef std::vector<istream_ptr_type, std::allocator<istream_ptr_type> > istream_ptr_set_type;
      
      ostream_ptr_set_type ostream(mpi_size);
      istream_ptr_set_type istream(mpi_size);
      
      for (int rank = 1; rank < mpi_size; ++ rank) {
	ostream[rank].reset(new ostream_type(rank, line_tag, 4096));
	istream[rank].reset(new istream_type(rank, line_tag, 4096));
      }
      
      std::string line;
      value_type value(0, std::string());
      value_type value_recv(0, std::string());
      
      int non_found_iter = 0;
      
      while (value.first != id_type(-1)) {
	bool found = false;
	
	for (int rank = 1; rank < mpi_size && value.first != id_type(-1); ++ rank)
	  if (ostream[rank]->test() && queue_is.pop(value, true) && value.first != id_type(-1)) {
	    ostream[rank]->write(utils::lexical_cast<std::string>(value.first) + ' ' + value.second);
	    
	    found = true;
	  }
	
	if (queue_send.empty() && queue_is.pop(value, true) && value.first != id_type(-1)) {
	  queue_send.push(value);
	  
	  found = true;
	}
	
	// reduce...
	for (int rank = 1; rank < mpi_size; ++ rank)
	  if (istream[rank] && istream[rank]->test()) {
	    if (istream[rank]->read(line)) {
	      tokenize(line, value_recv);
	      
	      queue_recv.push_swap(value_recv);
	    } else {
	      queue_recv.push(std::make_pair(id_type(-1), std::string()));
	      istream[rank].reset();
	    }
	    
	    found = true;
	  }
	
	non_found_iter = loop_sleep(found, non_found_iter);
      }
      
      bool terminated = false;
      
      for (;;) {
	bool found = false;
	
	if (! terminated && queue_send.push(std::make_pair(id_type(-1), std::string()), true)) {
	  terminated = true;
	  
	  found = true;
	}
	
	// termination...
	for (int rank = 1; rank < mpi_size; ++ rank)
	  if (ostream[rank] && ostream[rank]->test()) {
	    if (! ostream[rank]->terminated())
	      ostream[rank]->terminate();
	    else
	      ostream[rank].reset();
	    
	    found = true;
	  }
	
	// reduce...
	for (int rank = 1; rank < mpi_size; ++ rank)
	  if (istream[rank] && istream[rank]->test()) {
	    if (istream[rank]->read(line)) {
	      tokenize(line, value_recv);
	      
	      queue_recv.push_swap(value_recv);
	    } else {
	      queue_recv.push(std::make_pair(id_type(-1), std::string()));
	      istream[rank].reset();
	    }
	    
	    found = true;
	  }
	
	// termination condition!
	if (std::count(istream.begin(), istream.end(), istream_ptr_type()) == mpi_size
	    && std::count(ostream.begin(), ostream.end(), ostream_ptr_type()) == mpi_size
	    && terminated) break;
	
	non_found_iter = loop_sleep(found, non_found_iter);
      }
      
      mapper.join();
      reducer.join();
      consumer.join();
      merger.join();
    } else {
      subprocess_type subprocess(command);
      
      queue_type    queue_send(1);
      queue_id_type queue_id;
      queue_type    queue_recv;
      
      boost::thread mapper(mapper_type(queue_send, queue_id, subprocess));
      boost::thread reducer(reducer_type(queue_recv, queue_id, subprocess));

      typedef utils::mpi_istream        istream_type;
      typedef utils::mpi_ostream_simple ostream_type;
      
      boost::shared_ptr<istream_type> is(new istream_type(0, line_tag, 4096));
      boost::shared_ptr<ostream_type> os(new ostream_type(0, line_tag, 4096));
      
      std::string line;
      value_type value;

      bool terminated = false;
      
      int non_found_iter = 0;
      for (;;) {
	bool found = false;
	
	if (is && is->test() && queue_send.empty()) {
	  if (is->read(line))
	    tokenize(line, value);
	  else {
	    value.first  = id_type(-1);
	    value.second = std::string();
	    
	    is.reset();
	  }
	  
	  queue_send.push_swap(value);
	  
	  found = true;
	}
	
	if (! terminated) {
	  if (os && os->test() && queue_recv.pop_swap(value, true)) {
	    if (value.first == id_type(-1))
	      terminated = true;
	    else
	      os->write(utils::lexical_cast<std::string>(value.first) + ' ' + value.second);
	    
	    found = true;
	  }
	} else {
	  if (os && os->test()) {
	    if (! os->terminated())
	      os->terminate();
	    else
	      os.reset();
	    found = true;
	  }
	}
	
	if (! is && ! os) break;
	
	non_found_iter = loop_sleep(found, non_found_iter);
      }
      
      mapper.join();
      reducer.join();
    }
    
    // synchronize...
    if (mpi_rank == 0) {
      std::vector<MPI::Request, std::allocator<MPI::Request> > request_recv(mpi_size);
      std::vector<MPI::Request, std::allocator<MPI::Request> > request_send(mpi_size);
      std::vector<bool, std::allocator<bool> > terminated_recv(mpi_size, false);
      std::vector<bool, std::allocator<bool> > terminated_send(mpi_size, false);
    
      terminated_recv[0] = true;
      terminated_send[0] = true;
      for (int rank = 1; rank != mpi_size; ++ rank) {
	request_recv[rank] = MPI::COMM_WORLD.Irecv(0, 0, MPI::INT, rank, notify_tag);
	request_send[rank] = MPI::COMM_WORLD.Isend(0, 0, MPI::INT, rank, notify_tag);
      }
    
      int non_found_iter = 0;
      for (;;) {
	bool found = false;
      
	for (int rank = 1; rank != mpi_size; ++ rank)
	  if (! terminated_recv[rank] && request_recv[rank].Test()) {
	    terminated_recv[rank] = true;
	    found = true;
	  }
      
	for (int rank = 1; rank != mpi_size; ++ rank)
	  if (! terminated_send[rank] && request_send[rank].Test()) {
	    terminated_send[rank] = true;
	    found = true;
	  }
      
	if (std::count(terminated_send.begin(), terminated_send.end(), true) == mpi_size
	    && std::count(terminated_recv.begin(), terminated_recv.end(), true) == mpi_size) break;
      
	non_found_iter = loop_sleep(found, non_found_iter);
      }
    } else {
      MPI::Request request_send = MPI::COMM_WORLD.Isend(0, 0, MPI::INT, 0, notify_tag);
      MPI::Request request_recv = MPI::COMM_WORLD.Irecv(0, 0, MPI::INT, 0, notify_tag);
    
      bool terminated_send = false;
      bool terminated_recv = false;
    
      int non_found_iter = 0;
      for (;;) {
	bool found = false;
      
	if (! terminated_send && request_send.Test()) {
	  terminated_send = true;
	  found = true;
	}
      
	if (! terminated_recv && request_recv.Test()) {
	  terminated_recv = true;
	  found = true;
	}
      
	if (terminated_send && terminated_recv) break;
      
	non_found_iter = loop_sleep(found, non_found_iter);
      }
    }
  }
  catch (const std::exception& err) {
    std::cerr << "error: " << argv[0] << " "<< err.what() << std::endl;
    MPI::COMM_WORLD.Abort(1);
    return 1;
  }
  return 0;
}
Beispiel #21
0
int main (int argc, char* argv[]) {
	int cmd_start_index;
	int i;
	pid_t pid, hardlimit_monitor;

	init_default_limits ();
	cmd_start_index = parse_args (argc, argv);

	if (limit_timehard < 1 + (int)  (limit_time))
		limit_timehard = 1 + (int)  (limit_time);
	
	/* close inherited file descriptors. Is there a better way? */
	for (i = 3; i < (1<<16); i++)
		close (i);
	
	pid = fork();
	if (pid==0) {
		return subprocess (argc - cmd_start_index, argv + cmd_start_index);
	}
	
	hardlimit_monitor = fork ();
	if (hardlimit_monitor == 0) {
		sleep (6*limit_timehard);
		kill (pid, 9);
		return 0;
	}
	
	int status; 
	struct rusage usage ;  
	

	wait4(pid,&status, 0, &usage); //Wait for child to terminate
	kill (hardlimit_monitor, 9);
	waitpid (hardlimit_monitor, NULL, 0);
	
	fflush(stderr) ; /* ordering of output of child and parent should be right */
		
	double usertime = (float) (usage.ru_utime.tv_sec) + ((float) usage.ru_utime.tv_usec)/1000000 ;
	double systime = (float) (usage.ru_stime.tv_sec) + ((float)usage.ru_stime.tv_usec)/1000000 ;

	if(WIFSIGNALED(status)) {
		int signal = WTERMSIG(status);
				
		#define die(s) { fprintf(stderr,s) ; exit(0) ; }
		if(signal==SIGXCPU) die("TLE Time limit exceeded (H)\n");
		if(signal==SIGFPE)  die("FPE Floating point exception\n");
		if(signal==SIGILL)  die("ILL Illegal instruction\n");
		if(signal==SIGSEGV) die("SEG Segmentation fault\n");
		if(signal==SIGABRT) die("ABRT Aborted (got SIGABRT)\n");
		if(signal==SIGBUS)  die("BUS Bus error (bad memory access)\n");
		if(signal==SIGSYS)  die("SYS Invalid system call\n");
		if(signal==SIGXFSZ) die("XFSZ Output file too large\n");
		if(signal==SIGKILL) die("KILL Your program was killed (probably because of excessive memory usage)\n");
		
		die("UNK Unknown error, possibly your program does not return 0, or maybe its some fault of ours!");
	}
	
	
	
	if (usertime + systime > limit_time) die("TLE Time Limit exceeded\n") ;
	
	if (!WIFEXITED(status)) {
		fprintf (stderr,"EXIT Program exited abnormally. This could be due to excessive memory usage, or any runtime error that is impossible to determine.\n");
		exit (0);
	}
	
	if (WEXITSTATUS(status) != 0) { 
		fprintf (stderr,"EXIT Program did not return 0\n", WEXITSTATUS(status));
		exit (0);
	}
	
	return 0;
}
Beispiel #22
0
static Future<string> launch(
    const string& path,
    const vector<string>& argv)
{
  Try<Subprocess> s = subprocess(
      path,
      argv,
      Subprocess::PATH("/dev/null"),
      Subprocess::PIPE(),
      Subprocess::PIPE());

  string command = strings::join(
      ", ",
      path,
      strings::join(", ", argv));

  if (s.isError()) {
    return Failure(
        "Failed to execute the subprocess '" + command + "': " + s.error());
  }

  return await(
      s.get().status(),
      process::io::read(s.get().out().get()),
      process::io::read(s.get().err().get()))
    .then([command](const tuple<
        Future<Option<int>>,
        Future<string>,
        Future<string>>& t) -> Future<string> {
      Future<Option<int>> status = std::get<0>(t);
      if (!status.isReady()) {
        return Failure(
            "Failed to get the exit status of the subprocess: " +
            (status.isFailed() ? status.failure() : "discarded"));
      }

      if (status->isNone()) {
        return Failure("Failed to reap the subprocess");
      }

      if (status->get() != 0) {
        Future<string> error = std::get<2>(t);
        if (!error.isReady()) {
            return Failure(
                "Unexpected result from the subprocess: " +
                 WSTRINGIFY(status->get()) + ", stderr='" +
                 error.get() + "'");
        }

        return Failure("Subprocess '" + command + "' failed: " + error.get());
      }

      Future<string> output = std::get<1>(t);
      if (!output.isReady()) {
         return Failure(
            "Failed to read stdout from '" + command + "': " +
            (output.isFailed() ? output.failure() : "discarded"));
      }

      return output;
    });
}