/* * argv[0]: command * argv[1]: for detail output * argv[2]: kmemcache.ko path * argv[3]: umemcached command * argv[4]: args of umemcached */ int main(int argc, char *argv[]) { assert(argc > 4); if (!strcmp(argv[1], "0")) close_terminal(); start_kmc_server(argv + 2); return 0; }
ErrorCode ProcessSpawner::run(std::function<bool()> preExecAction) { if (_pid != 0 || _executablePath.empty()) return kErrorInvalidArgument; // // If we have redirection, prepare pipes and handles. // int fds[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}}; int term[2] = {-1, -1}; bool startRedirectThread = false; for (size_t n = 0; n < 3; n++) { switch (_descriptors[n].mode) { case kRedirectConsole: // do nothing break; case kRedirectNull: if (n == 0) { fds[n][RD] = ::open("/dev/null", O_RDONLY); } else { fds[n][WR] = ::open("/dev/null", O_WRONLY); } break; case kRedirectFile: if (n == 0) { fds[n][RD] = ::open(_descriptors[n].path.c_str(), O_RDONLY); } else { fds[n][WR] = ::open(_descriptors[n].path.c_str(), O_RDWR); if (fds[n][WR] < 0) { fds[n][WR] = ::open(_descriptors[n].path.c_str(), O_CREAT | O_RDWR, 0600); } } break; case kRedirectBuffer: _outputBuffer.clear(); // fall-through case kRedirectDelegate: startRedirectThread = true; if (term[0] == -1) { if (!open_terminal(term)) { return Platform::TranslateError(); } } fds[n][RD] = term[RD]; fds[n][WR] = term[WR]; break; } } _pid = ::fork(); if (_pid < 0) { close_terminal(term); return kErrorNoMemory; } if (_pid == 0) { if (::setgid(::getgid()) == 0) { ::setsid(); for (size_t n = 0; n < 3; n++) { switch (_descriptors[n].mode) { case kRedirectConsole: // do nothing break; case kRedirectDelegate: // // We are using the same virtual terminal for all delegate // redirections, so dup2() only, do not close. We will close when all // FDs have been dup2()'d. // ::dup2(fds[n][WR], n); break; default: if (n == 0) { if (fds[n][WR] != -1) { ::close(fds[n][WR]); } ::dup2(fds[n][RD], n); ::close(fds[n][RD]); } else { if (fds[n][RD] != -1) { ::close(fds[n][RD]); } ::dup2(fds[n][WR], n); ::close(fds[n][WR]); } break; } } close_terminal(term); if (!_workingDirectory.empty()) { ::chdir(_workingDirectory.c_str()); } std::vector<char *> args; args.push_back(const_cast<char *>(_executablePath.c_str())); for (auto const &e : _arguments) args.push_back(const_cast<char *>(e.c_str())); args.push_back(nullptr); std::vector<char *> environment; for (auto const &env : _environment) environment.push_back(const_cast<char *>( (new std::string(env.first + '=' + env.second))->c_str())); environment.push_back(nullptr); if (!preExecAction()) return kErrorUnknown; if (::execve(_executablePath.c_str(), &args[0], &environment[0]) < 0) { DS2LOG(Error, "cannot spawn executable %s, error=%s", _executablePath.c_str(), strerror(errno)); } } ::_exit(127); } ::close(term[WR]); for (size_t n = 0; n < 3; n++) { switch (_descriptors[n].mode) { case kRedirectConsole: // do nothing break; case kRedirectDelegate: _descriptors[n].fd = term[RD]; break; default: if (n == 0) { if (fds[n][RD] != -1) { ::close(fds[n][RD]); _descriptors[n].fd = fds[n][WR]; } } else { if (fds[n][WR] != -1) { ::close(fds[n][WR]); _descriptors[n].fd = fds[n][RD]; } } break; } } if (startRedirectThread) { _delegateThread = std::thread(&ProcessSpawner::redirectionThread, this); } return kSuccess; }