ProcessMonitor.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:4k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998, 1999  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log$
  21.  */
  22. #include <unistd.h>
  23. #include <stddef.h>
  24. #include <errno.h>
  25. #include <string.h>
  26. #include <signal.h>
  27. #include <sys/types.h>
  28. #include <sys/wait.h>
  29. #include "ProcessMonitor.h"
  30. #include "xcdrdao.h"
  31. #include "util.h"
  32. static char rcsid[] = "$Id$";
  33. Process::Process(int pid, int commFd)
  34. {
  35.   pid_ = pid;
  36.   commFd_ = commFd;
  37.   exited_ = 0;
  38.   exitStatus_ = 0;
  39.   next_ = NULL;
  40. }
  41. Process::~Process()
  42. {
  43.   if (commFd_ >= 0)
  44.     close(commFd_);
  45.   next_ = NULL;
  46. }
  47. int Process::pid() const
  48. {
  49.   return pid_;
  50. }
  51. int Process::commFd() const
  52. {
  53.   return commFd_;
  54. }
  55. int Process::exited() const
  56. {
  57.   return exited_;
  58. }
  59. int Process::exitStatus() const
  60. {
  61.   return exitStatus_;
  62. }
  63. ProcessMonitor::ProcessMonitor()
  64. {
  65.   processes_ = NULL;
  66.   statusChanged_ = 0;
  67. }
  68. ProcessMonitor::~ProcessMonitor()
  69. {
  70.   Process *next;
  71.   blockProcessMonitorSignals();
  72.   while (processes_ != NULL) {
  73.     next = processes_->next_;
  74.     delete processes_;
  75.     processes_ = next;
  76.   }
  77.   unblockProcessMonitorSignals();
  78. }
  79. int ProcessMonitor::statusChanged()
  80. {
  81.   int s = statusChanged_;
  82.   statusChanged_ = 0;
  83.   return s;
  84. }
  85. Process *ProcessMonitor::start(const char *prg, char *const args[])
  86. {
  87.   int pid;
  88.   Process *p;
  89.   int pipeFds[2];
  90.   if (pipe(pipeFds) != 0) {
  91.     message(-2, "Cannot create pipe: %s", strerror(errno));
  92.     return NULL;
  93.   }
  94.   
  95.   blockProcessMonitorSignals();
  96.   pid = fork();
  97.   if (pid == 0) {
  98.     // we are the new process
  99.     // detach from controlling terminal
  100.     setsid();
  101.     // close reading end of pipe
  102.     close(pipeFds[0]);
  103.     if (pipeFds[1] != 3) {
  104.       dup2(pipeFds[1], 3/*fileno(stdout)*/);
  105.       close(pipeFds[1]);
  106.     }
  107.     execvp(prg, args);
  108.     message(-2, "Cannot execute '%s': %s", prg, strerror(errno));
  109.     _exit(255);
  110.   }
  111.   else if (pid < 0) {
  112.     message(-2, "Cannot fork: %s", strerror(errno));
  113.     unblockProcessMonitorSignals();
  114.     return NULL;
  115.   }
  116.   // close writing end of pipe
  117.   close(pipeFds[1]);
  118.   p = new Process(pid, pipeFds[0]);
  119.   
  120.   p->next_ = processes_;
  121.   processes_ = p;
  122.   unblockProcessMonitorSignals();
  123.   return p;
  124. }
  125. Process *ProcessMonitor::find(Process *p, Process **pred)
  126. {
  127.   Process *run;
  128.   for (*pred = NULL, run = processes_; run != NULL;
  129.        *pred = run, run = run->next_) {
  130.     if (p == run) {
  131.       return run;
  132.     }
  133.   }
  134.   return NULL;
  135. }
  136. Process *ProcessMonitor::find(int pid)
  137. {
  138.   Process *run;
  139.   for (run = processes_; run != NULL; run = run->next_) {
  140.     if (run->pid() == pid) {
  141.       return run;
  142.     }
  143.   }
  144.   return NULL;
  145. }
  146. void ProcessMonitor::stop(Process *p)
  147. {
  148.   kill(p->pid(), SIGTERM);
  149. }
  150. void ProcessMonitor::remove(Process *p)
  151. {
  152.   Process *act, *pred;
  153.   blockProcessMonitorSignals();
  154.   if ((act = find(p, &pred)) != NULL) {
  155.     if (pred == NULL)
  156.       processes_ = act->next_;
  157.     else
  158.       pred->next_ = act->next_;
  159.     delete act;
  160.   }
  161.   unblockProcessMonitorSignals();
  162. }
  163. void ProcessMonitor::handleSigChld()
  164. {
  165.   int pid;
  166.   Process *p;
  167.   int status;
  168.   
  169.   while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
  170.     if ((p = find(pid)) != NULL) {
  171.       p->exited_ = 1;
  172.       
  173.       if (WIFEXITED(status)) {
  174. p->exitStatus_ = WEXITSTATUS(status);
  175.       }
  176.       else if (WIFSIGNALED(status)) {
  177. p->exitStatus_ = 254;
  178.       }
  179.       else {
  180. p->exitStatus_ = 253;
  181.       }
  182.       statusChanged_ = 1;
  183.     }
  184.     else {
  185.       message(-3, "Unknown child with pid %d exited.", pid);
  186.     }
  187.   }
  188.   /*
  189.   if (pid < 0) 
  190.     message(-2, "waitpid failed: %s", strerror(errno));
  191.     */
  192. }