зеркало из https://github.com/mozilla/gecko-dev.git
Bug 772734 - Fixes LaunchApp hang when launching. r=cjones
From c6bdfcf39e3dfe28fe7376f8c0b1b9d07a1d969b Mon Sep 17 00:00:00 2001 plugin-container - v4 Added checks in case PR_DuplicateEnvironment or PR_Malloc fail Added #ifdef so that only Android builds try to call PR_DuplicateEnvironment --- ipc/chromium/src/base/process_util_linux.cc | 121 +++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 6 deletions(-)
This commit is contained in:
Родитель
a6e3f86e5c
Коммит
b19b3adfb8
|
@ -7,6 +7,7 @@
|
|||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
|
@ -19,6 +20,19 @@
|
|||
#include "base/string_tokenizer.h"
|
||||
#include "base/string_util.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
/*
|
||||
* Currently, PR_DuplicateEnvironment is implemented in mozglue/build/BionicGlue.cpp
|
||||
*/
|
||||
#define HAVE_PR_DUPLICATE_ENVIRONMENT
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prenv.h"
|
||||
#include "prmem.h"
|
||||
/* Temporary until we have PR_DuplicateEnvironment in prenv.h */
|
||||
extern "C" { NSPR_API(char **)PR_DuplicateEnvironment(void); }
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
enum ParsingState {
|
||||
|
@ -32,6 +46,87 @@ static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
|
|||
|
||||
namespace base {
|
||||
|
||||
#ifdef HAVE_PR_DUPLICATE_ENVIRONMENT
|
||||
class EnvironmentEnvp
|
||||
{
|
||||
public:
|
||||
EnvironmentEnvp()
|
||||
: mEnvp(PR_DuplicateEnvironment()) {}
|
||||
|
||||
EnvironmentEnvp(const environment_map &em)
|
||||
{
|
||||
mEnvp = (char **)PR_Malloc(sizeof(char *) * (em.size() + 1));
|
||||
if (!mEnvp) {
|
||||
return;
|
||||
}
|
||||
char **e = mEnvp;
|
||||
for (environment_map::const_iterator it = em.begin();
|
||||
it != em.end(); ++it, ++e) {
|
||||
std::string str = it->first;
|
||||
str += "=";
|
||||
str += it->second;
|
||||
*e = PL_strdup(str.c_str());
|
||||
}
|
||||
*e = NULL;
|
||||
}
|
||||
|
||||
~EnvironmentEnvp()
|
||||
{
|
||||
if (!mEnvp) {
|
||||
return;
|
||||
}
|
||||
for (char **e = mEnvp; *e; ++e) {
|
||||
PL_strfree(*e);
|
||||
}
|
||||
PR_Free(mEnvp);
|
||||
}
|
||||
|
||||
char * const *AsEnvp() { return mEnvp; }
|
||||
|
||||
void ToMap(environment_map &em)
|
||||
{
|
||||
if (!mEnvp) {
|
||||
return;
|
||||
}
|
||||
em.clear();
|
||||
for (char **e = mEnvp; *e; ++e) {
|
||||
const char *eq;
|
||||
if ((eq = strchr(*e, '=')) != NULL) {
|
||||
std::string varname(*e, eq - *e);
|
||||
em[varname.c_str()] = &eq[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
char **mEnvp;
|
||||
};
|
||||
|
||||
class Environment : public environment_map
|
||||
{
|
||||
public:
|
||||
Environment()
|
||||
{
|
||||
EnvironmentEnvp envp;
|
||||
envp.ToMap(*this);
|
||||
}
|
||||
|
||||
char * const *AsEnvp() {
|
||||
mEnvp.reset(new EnvironmentEnvp(*this));
|
||||
return mEnvp->AsEnvp();
|
||||
}
|
||||
|
||||
void Merge(const environment_map &em)
|
||||
{
|
||||
for (const_iterator it = em.begin(); it != em.end(); ++it) {
|
||||
(*this)[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::auto_ptr<EnvironmentEnvp> mEnvp;
|
||||
};
|
||||
#endif // HAVE_PR_DUPLICATE_ENVIRONMENT
|
||||
|
||||
bool LaunchApp(const std::vector<std::string>& argv,
|
||||
const file_handle_mapping_vector& fds_to_remap,
|
||||
bool wait, ProcessHandle* process_handle) {
|
||||
|
@ -50,6 +145,16 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
|||
fd_shuffle1.reserve(fds_to_remap.size());
|
||||
fd_shuffle2.reserve(fds_to_remap.size());
|
||||
|
||||
#ifdef HAVE_PR_DUPLICATE_ENVIRONMENT
|
||||
Environment env;
|
||||
env.Merge(env_vars_to_set);
|
||||
char * const *envp = env.AsEnvp();
|
||||
if (!envp) {
|
||||
DLOG(ERROR) << "FAILED to duplicate environment for: " << argv_cstr[0];
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
return false;
|
||||
|
@ -66,19 +171,23 @@ bool LaunchApp(const std::vector<std::string>& argv,
|
|||
|
||||
CloseSuperfluousFds(fd_shuffle2);
|
||||
|
||||
for (size_t i = 0; i < argv.size(); i++)
|
||||
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
|
||||
argv_cstr[argv.size()] = NULL;
|
||||
|
||||
#ifdef HAVE_PR_DUPLICATE_ENVIRONMENT
|
||||
execve(argv_cstr[0], argv_cstr.get(), envp);
|
||||
#else
|
||||
for (environment_map::const_iterator it = env_vars_to_set.begin();
|
||||
it != env_vars_to_set.end(); ++it) {
|
||||
if (setenv(it->first.c_str(), it->second.c_str(), 1/*overwrite*/))
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < argv.size(); i++)
|
||||
argv_cstr[i] = const_cast<char*>(argv[i].c_str());
|
||||
argv_cstr[argv.size()] = NULL;
|
||||
execvp(argv_cstr[0], argv_cstr.get());
|
||||
execv(argv_cstr[0], argv_cstr.get());
|
||||
#endif
|
||||
// if we get here, we're in serious trouble and should complain loudly
|
||||
DLOG(ERROR) << "FAILED TO exec() CHILD PROCESS, path: " << argv_cstr[0];
|
||||
exit(127);
|
||||
_exit(127);
|
||||
} else {
|
||||
gProcessLog.print("==> process %d launched child process %d\n",
|
||||
GetCurrentProcId(), pid);
|
||||
|
|
Загрузка…
Ссылка в новой задаче