jeudi 2 novembre 2017

Why execve hang

I have a struct storing file, argv, and envp in C++ STL containers. The struct also has methods that transform them to c-style pointers for execve call.

struct Foo {
  std::string file;
  std::vector <std::string> argv;
  std::unordered_map <std::string, std::string> envp;

  inline auto c_file() const;
  inline auto c_argv() const;
  inline auto c_envp() const;
}

// Function: c_file
inline auto Foo::c_file() const {
  return file.c_str();
}

// Function: c_argv
inline auto Foo::c_argv() const {

  auto ptr = std::make_unique<char*[]>(argv.size() + 1);
  for(size_t i=0; i<argv.size(); ++i) {
    ptr[i] = const_cast<char*>(argv[i].c_str());
  }
  ptr[argv.size()] = nullptr;

  return ptr;
}

// Function: c_envp
inline auto Foo::c_envp() const {

  std::unique_ptr<char*, std::function<void(char**)>> ptr(
    new char*[envp.size() + 1],
    [sz=envp.size()+1](char** ptr) {
      for(size_t i=0; i<sz; ++i) {
        delete [] ptr[i];
      }
      delete [] ptr;
    }
  );

  auto idx = size_t{0};

  for(const auto& kvp : envp) {
    auto entry = kvp.first + "=" + kvp.second;
    ptr.get()[idx] = new char[entry.size() + 1];
    ::strncpy(ptr.get()[idx], entry.c_str(), entry.size() + 1);
    ++idx;
  }
  ptr.get()[idx] = nullptr;

  return ptr;
}

In my program, I use the following way to call execve.

void child_entry(const Foo& foo) {
  ::execve(foo.c_file(), foo.c_argv().get(), foo.c_envp().get());
}

However, the call to execve sometimes hang without any response. This makes my parent process fail to synchronize with the child process (through a pipe close-on-exec). Is there anything wrong with my idea here of using unique_ptr?

Aucun commentaire:

Enregistrer un commentaire