18 #include <ndb_global.h> 
   24 #include <BaseString.hpp> 
   25 #include <InputStream.hpp> 
   38 #include <sys/resource.h> 
   43   fprintf(f, 
"define process\n");
 
   44   fprintf(f, 
"id: %d\n",    
m_id);
 
   65   props.get(
"id", (Uint32 *) &m_id);
 
   66   props.get(
"name", m_name);
 
   67   props.get(
"group", m_group);
 
   68   props.get(
"env", m_env);
 
   69   props.get(
"path", m_path);
 
   70   props.get(
"args", m_args);
 
   71   props.get(
"cwd", m_cwd);
 
   72   props.get(
"owner", m_owner);
 
   73   props.get(
"type", m_type);
 
   74   props.get(
"runas", m_runas);
 
   76   props.get(
"stdin", m_stdin);
 
   77   props.get(
"stdout", m_stdout);
 
   78   props.get(
"stderr", m_stderr);
 
   79   props.get(
"ulimit", m_ulimit);
 
   80   props.get(
"shutdown", m_shutdown_options);
 
   83   if(strcasecmp(m_type.c_str(), 
"temporary") == 0){
 
   84     m_processType = TEMPORARY;
 
   87     logger.critical(
"Process type must be 'temporary' on windows");
 
   90     m_processType = PERMANENT;
 
  103       if(m_processType == TEMPORARY){
 
  111     assert(!isRunning());
 
  121   if (is_bad_pid(m_pid)) {
 
  131   if (!(proc = OpenProcess(PROCESS_QUERY_INFORMATION, 0, m_pid)))
 
  133     logger.debug(
"Cannot OpenProcess with pid: %d, error: %d",
 
  134                  m_pid, GetLastError());
 
  139   if (GetExitCodeProcess(proc, &exitcode) && exitcode != STILL_ACTIVE)
 
  148   int s = 
kill((pid_t)-m_pid, 0); 
 
  153       logger.critical(
"Not enough privileges to control pid %d\n", m_pid);
 
  160       logger.critical(
"Cannot not control pid %d: %s\n", m_pid, strerror(errno));
 
  171   if (!is_bad_pid(m_pid)) {
 
  172     logger.critical(
"Reading pid while having valid process (%d)", m_pid);
 
  176   char filename[PATH_MAX*2+1];
 
  180   memset(buf, 0, 
sizeof(buf));
 
  184   f = fopen(filename, 
"r");
 
  191   size_t r = fread(buf, 1, 
sizeof(buf), f);
 
  194     m_pid = strtol(buf, (
char **)NULL, 0);
 
  203 inline int mkstemp(
char *tmp)
 
  209   fd = _open(tmp, _O_CREAT|_O_RDWR|_O_TEXT|_O_TRUNC, _S_IREAD|_S_IWRITE);
 
  216   char tmpfilename[PATH_MAX+1+4+8];
 
  217   char filename[PATH_MAX*2+1];
 
  223   int fd = mkstemp(tmpfilename);
 
  225     logger.error(
"Cannot open `%s': %s\n", tmpfilename, strerror(errno));
 
  232     logger.error(
"Cannot open `%s': %s\n", tmpfilename, strerror(errno));
 
  236   fprintf(f, 
"%d", pid);
 
  243   if(rename(tmpfilename, filename) == -1){
 
  244     logger.error(
"Unable to rename from %s to %s", tmpfilename, filename);
 
  251 setup_environment(
const char *env) {
 
  254   for(
int i = 0; p[
i] != NULL; 
i++){
 
  262 #ifdef HAVE_GETRLIMIT 
  265   pair.
split(list, 
":");
 
  266   if(list.size() != 2){
 
  267     logger.error(
"Unable to process ulimit: split >%s< list.size()=%d", 
 
  268                  pair.
c_str(), list.size());
 
  273   rlim_t value = RLIM_INFINITY;
 
  274   if(!(list[1].trim() == 
"unlimited")){
 
  275     value = atoi(list[1].c_str());
 
  279 #define _RLIMIT_FIX(x) { res = getrlimit(x,&rlp); if(!res){ rlp.rlim_cur = value; res = setrlimit(x, &rlp); }} 
  281   if(list[0].trim() == 
"c"){
 
  282     _RLIMIT_FIX(RLIMIT_CORE);
 
  283   } 
else if(list[0] == 
"d"){
 
  284     _RLIMIT_FIX(RLIMIT_DATA);
 
  285   } 
else if(list[0] == 
"f"){
 
  286     _RLIMIT_FIX(RLIMIT_FSIZE);
 
  287   } 
else if(list[0] == 
"n"){
 
  288     _RLIMIT_FIX(RLIMIT_NOFILE);
 
  289   } 
else if(list[0] == 
"s"){
 
  290     _RLIMIT_FIX(RLIMIT_STACK);
 
  291   } 
else if(list[0] == 
"t"){
 
  292     _RLIMIT_FIX(RLIMIT_CPU);
 
  298     logger.error(
"Unable to process ulimit: %s res=%d error=%d(%s)", 
 
  299                  pair.
c_str(), res, errno, strerror(errno));
 
  307 const int S_IRUSR = _S_IREAD, S_IWUSR = _S_IWRITE;
 
  315     logger.error(
"Could not argify new environment");
 
  319   for(
int i = 0; ptr[
i] != NULL; 
i++) {
 
  323     char *str1 = strdup(ptr[i]);
 
  327     *strchr(str1, 
'=') = 0;
 
  329     bs.
assfmt(
"%s=%s", str1, str2 ? str2 : 
"");
 
  336 CPCD::Process::do_exec() {
 
  342   save_environment(m_env.c_str(), saved);
 
  345   setup_environment(m_env.c_str());
 
  349   if(strlen(m_cwd.c_str()) > 0) {
 
  354       logger.critical(
"Couldn't getcwd before spawn");
 
  357     int err = chdir(m_cwd.c_str());
 
  360       logger.error(
"%s: %s\n", m_cwd.c_str(), strerror(errno));
 
  366   m_ulimit.split(ulimit);
 
  367   for(i = 0; i<ulimit.size(); i++){
 
  368     if(ulimit[i].trim().length() > 0 && set_ulimit(ulimit[i]) != 0){
 
  374   const char *nul = IF_WIN(
"nul:", 
"/dev/null");
 
  375   int fdnull = open(nul, O_RDWR, 0);
 
  377     logger.error(
"Cannot open `%s': %s\n", nul, strerror(errno));
 
  381   BaseString * redirects[] = { &m_stdin, &m_stdout, &m_stderr };
 
  386   for (i = 0; i < 3; i++) {
 
  388     std_dups[
i] = dup(i);
 
  390     if (redirects[i]->empty()) {
 
  397     if((* redirects[i]) == 
"2>&1" && i == 2){
 
  406     int mode = S_IRUSR | S_IWUSR ;
 
  410       flags |= O_WRONLY | O_CREAT | O_APPEND;
 
  412     int f = fds[
i]= open(redirects[i]->c_str(), flags, mode);
 
  414       logger.error(
"Cannot redirect %ld to/from '%s' : %s\n", i,
 
  415                    redirects[i]->c_str(), strerror(errno));
 
  426   for(i = STDERR_FILENO+1; (int)i < getdtablesize(); i++)
 
  429   execv(m_path.c_str(), argv);
 
  433   logger.error(
"Exec failed: %s\n", strerror(errno));
 
  438   FILE *fpipe = _popen(
"sh -c 'cygpath -w `which sh`'", 
"rt");
 
  441   require(fgets(buf, MAX_PATH - 1, fpipe));
 
  450   shcmd.
assfmt(
"%s -c '%s %s'", sh.
c_str(), m_path.c_str(), m_args.c_str());
 
  452   PROCESS_INFORMATION pi = {0};
 
  453   STARTUPINFO si = {
sizeof(STARTUPINFO), 0};
 
  455   si.dwFlags   |=  STARTF_USESTDHANDLES;
 
  456   si.hStdInput  = (HANDLE)_get_osfhandle(0);
 
  457   si.hStdOutput = (HANDLE)_get_osfhandle(1);
 
  458   si.hStdError  = (HANDLE)_get_osfhandle(2);
 
  460   if(!CreateProcessA(sh.
c_str(),
 
  461                      (LPSTR)shcmd.
c_str(),
 
  472     DWORD err = GetLastError();
 
  474     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 
  475                   FORMAT_MESSAGE_FROM_SYSTEM |
 
  476                   FORMAT_MESSAGE_IGNORE_INSERTS,
 
  479                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
  483     logger.error(
"CreateProcess failed, error: %d, message: '%s'",
 
  489   HANDLE proc = pi.hProcess;
 
  493   require(m_job = CreateJobObject(0, 0));
 
  494   require(AssignProcessToJobObject(m_job, proc));
 
  497   ResumeThread(pi.hThread);
 
  498   CloseHandle(pi.hThread);
 
  504     logger.critical(
"Couldn't go back to saved cwd after spawn()");
 
  505     logger.critical(
"errno: %d, strerror: %s", errno, strerror(errno));
 
  510   for(i = 0; i < 3; i++) {
 
  511     dup2(std_dups[i], i);
 
  515   for (i = 0; i < saved.size(); i++) {
 
  516     putenv(saved[i].c_str());
 
  519   logger.debug(
"'%s' has been started", shcmd.
c_str());
 
  522   BOOL result = GetExitCodeProcess(proc, &exitcode);
 
  524   if (result && exitcode != 259) {
 
  526     logger.warning(
"Process terminated early");
 
  529   int pid = GetProcessId(proc);
 
  531     logger.critical(
"GetProcessId failed, error: %d!", GetLastError());
 
  533   logger.debug(
"new pid %d", pid);
 
  563   logger.info(
"Starting %d: %s", m_id, m_name.c_str());
 
  567   switch(m_processType){
 
  574     switch(pid = fork()) {
 
  578       if(runas(m_runas.c_str()) == 0){
 
  579         signal(SIGCHLD, SIG_DFL);
 
  585       logger.error(
"Cannot fork: %s\n", strerror(errno));
 
  590       logger.debug(
"Started temporary %d : pid=%d", m_id, pid);
 
  605       signal(SIGCHLD, SIG_IGN);
 
  606       switch(pid = fork()) {
 
  610         if(runas(m_runas.c_str()) != 0){
 
  613         signal(SIGCHLD, SIG_DFL);
 
  619         logger.error(
"Cannot fork: %s\n", strerror(errno));
 
  624         logger.debug(
"Started permanent %d : pid=%d", m_id, pid);
 
  630       logger.error(
"Cannot fork: %s\n", strerror(errno));
 
  641     logger.critical(
"Unknown process type");
 
  645   while(readPid() < 0){
 
  650   pid_t pgid = IF_WIN(-1, getpgid(pid));
 
  652   if(pgid != -1 && pgid != m_pid){
 
  653     logger.error(
"pgid and m_pid don't match: %d %d (%d)", pgid, m_pid, pid);
 
  668   char filename[PATH_MAX*2+1];
 
  672   if (is_bad_pid(m_pid))
 
  674     logger.critical(
"Stopping process with bogus pid: %d id: %d", 
 
  684   if(m_shutdown_options == 
"SIGKILL")
 
  690     logger.debug(
"Sent SIGTERM to pid %d", (
int)-m_pid);
 
  693     logger.debug(
"kill pid: %d : %s", (
int)-m_pid, strerror(errno));
 
  699     ret = 
kill(-m_pid, SIGKILL);
 
  702       logger.debug(
"Sent SIGKILL to pid %d", (
int)-m_pid);
 
  705       logger.debug(
"kill pid: %d : %s\n", (
int)-m_pid, strerror(errno));
 
  714     require(proc = OpenProcess(PROCESS_QUERY_INFORMATION, 0, m_pid));
 
  715     require(IsProcessInJob(proc, m_job,  &truth));
 
  716     require(truth == TRUE);
 
  717     require(CloseHandle(proc));
 
  719     require(TerminateJobObject(m_job, 37));
 
  720     require(CloseHandle(m_job));