diff options
| -rw-r--r-- | include/Task.h | 1 | ||||
| -rw-r--r-- | include/TaskMan.h | 19 | ||||
| -rw-r--r-- | include/Variables.h | 1 | ||||
| -rw-r--r-- | lib/Task.cc | 16 | ||||
| -rw-r--r-- | lib/TaskMan.cc | 111 | ||||
| -rw-r--r-- | lib/Variables.cc | 6 | ||||
| -rw-r--r-- | src/Main.cc | 102 | 
7 files changed, 208 insertions, 48 deletions
| diff --git a/include/Task.h b/include/Task.h index b4d8b68..b6f9b2e 100644 --- a/include/Task.h +++ b/include/Task.h @@ -22,6 +22,7 @@ class Task : public Base {        virtual ~Task();      virtual String GetName();      int Run(); +    int DryRun();      int GetState();      void Suspend(int = -1) throw (GeneralException);      void WaitFor(Task *); diff --git a/include/TaskMan.h b/include/TaskMan.h index 8cd8e66..e61aa3f 100644 --- a/include/TaskMan.h +++ b/include/TaskMan.h @@ -2,9 +2,16 @@  #define __TASKMAN_H__  #ifdef __cplusplus +#include <signal.h>  #include <Task.h>  #include <vector.h> +#define E_BURST		0 +#define E_HANDLE	1 +#define E_PROCESS	2 +#define E_TIMEOUT	3 +#define E_TASK		4 +  class TaskMan : public Base {    public:      static void AddTask(Task *); @@ -13,10 +20,15 @@ class TaskMan : public Base {      static void Init() throw (GeneralException);      static void MainLoop() throw (GeneralException);      static void WaitFor(Handle *, Task *, int = 0); -    static void WaitFor(pid_t, Task *); +    static void WaitFor(pid_t, Task *, int = 0);      static void WaitFor(timeval, Task *, int = 0);      static int GotChild(pid_t, int);      static void Stop(); +    static int Event(); +    static Task * Etask(); +    static Handle * Ehandle(); +    static int Eprocess(); +    static int Estatus();      class w4ha_t {        public: @@ -53,6 +65,11 @@ class TaskMan : public Base {      static vector<w4pr_t> w4pr;      static vector<w4to_t> w4to;      static bool stopped; +    static int event; +    static Task * etask; +    static Handle * ehandle; +    static int eprocess, estatus; +    static sigset_t sigchildset;  };  #else diff --git a/include/Variables.h b/include/Variables.h index f3471bd..f4eb6db 100644 --- a/include/Variables.h +++ b/include/Variables.h @@ -10,6 +10,7 @@  class Variables : public Base {    public:        Variables(int = 0); +      Variables(const Variables &);        ~Variables();      void SetTo(int i, const String &);      String operator[](const String &); diff --git a/lib/Task.cc b/lib/Task.cc index 839c003..3cac327 100644 --- a/lib/Task.cc +++ b/lib/Task.cc @@ -33,6 +33,22 @@ int Task::Run() {      return state;  } +int Task::DryRun() { +    while (state != TASK_DONE) { +	try { +	    state = Do(); +	} +	catch (TaskSwitch) { +	} +	catch (GeneralException e) { +	    cerr << _("Task ") << GetName() << _(" caused an unexpected exception during dry-run: \"") << e.GetMsg() << _("\". Terminating.\n"); +	    state = TASK_DONE; +	} +    } +     +    return state; +} +  int Task::GetState() {      return state;  } diff --git a/lib/TaskMan.cc b/lib/TaskMan.cc index 3169f88..4d58be9 100644 --- a/lib/TaskMan.cc +++ b/lib/TaskMan.cc @@ -22,6 +22,12 @@ bool TaskMan::stopped = false;  int TaskMan::number = 0;  bool TaskMan::inited = false; +int TaskMan::event, TaskMan::eprocess, TaskMan::estatus; +Task * TaskMan::etask; +Handle * TaskMan::ehandle; + +sigset_t TaskMan::sigchildset; +  static int got_sigchild = 0;  void taskman_sigchild(int sig) { @@ -30,13 +36,17 @@ void taskman_sigchild(int sig) {      pid = wait(&status);      if (TaskMan::GotChild(pid, status)) { -	got_sigchild = 1; +	got_sigchild++; +    } else { +	TaskMan::WaitFor(pid, 0, status);      } +     +    cerr << "Got SIGCHILD, pid = " << pid << " and status = " << status << endl;      signal(SIGCHLD, taskman_sigchild);  } -void taskman_sigpipe(int sig) { -    signal(SIGPIPE, taskman_sigpipe); +void taskman_sighole(int sig) { +    signal(sig, taskman_sighole);  }  int TaskMan::GotChild(pid_t pid, int status) { @@ -59,7 +69,12 @@ void TaskMan::Init() throw (GeneralException) {      }      signal(SIGCHLD, taskman_sigchild); -    signal(SIGPIPE, taskman_sigpipe); +    signal(SIGPIPE, taskman_sighole); +    signal(SIGHUP, taskman_sighole); +     +    sigemptyset(&sigchildset); +    sigaddset(&sigchildset, SIGCHLD); +    sigprocmask(SIG_BLOCK, &sigchildset, 0);      inited = true;      number = 0; @@ -69,6 +84,26 @@ void TaskMan::Stop() {      stopped = true;  } +int TaskMan::Event() { +    return event; +} + +Task * TaskMan::Etask() { +    return etask; +} + +Handle * TaskMan::Ehandle() { +    return ehandle; +} + +int TaskMan::Eprocess() { +    return eprocess; +} + +int TaskMan::Estatus() { +    return estatus; +} +  void TaskMan::AddTask(Task * t) {      if (!inited) {  	Init(); @@ -132,8 +167,19 @@ void TaskMan::WaitFor(Handle * h, Task * t, int flags) {      w4ha.push_back(w4ha_t(h, flags, t));  } -void TaskMan::WaitFor(pid_t p, Task * t) { -    w4pr.push_back(w4pr_t(p, t)); +void TaskMan::WaitFor(pid_t pid, Task * t, int status) { +    if (status == -1) { +	for (vector<w4pr_t>::iterator p = w4pr.begin(); p && (p != w4pr.end()); p++) { +	    if (p->pr == pid) { +		p->T = t; +		p->flag = true; +		got_sigchild++; +		return; +	    } +	} +    } +    w4pr.push_back(w4pr_t(pid, t)); +    w4pr[w4pr.size() - 1].status = status;  }  void TaskMan::WaitFor(timeval t, Task * T, int flags) { @@ -163,19 +209,24 @@ void TaskMan::MainLoop() throw (GeneralException) {  	while (!no_burst) {  	    no_burst = 1;              /* First, we will check for any burning task and run 'em */ +	    event = E_BURST;  	    for (TaskList_t::iterator p = TaskList.begin(); p && (p != TaskList.end()); p++) {  		Task * t = *p; -//		cerr << "-=- TaskMan: task " << t->GetName() << endl; - +		cerr << "-=- TaskMan: task " << t->GetName() << endl; +		 +		if (t->IsStopped()) { +		    continue; +		} +		  		if (t->GetState() == TASK_BURST) { -		    cerr << "-=- TaskMan: running burning task " << t->GetName() << endl; +//		    cerr << "-=- TaskMan: running burning task " << t->GetName() << endl;  		    t->Run();  		    /* if the task added some new tasks, we have to rerun the loop */  		    no_burst = 0;  		    break;  		} -	     +		  		if (t->GetState() == TASK_DONE) {  		    TaskList.erase(p);  		    number--; @@ -185,6 +236,10 @@ void TaskMan::MainLoop() throw (GeneralException) {  	    }  	} +	/* Now is time to check all the handle and enters into a wait state. */ + +	event = E_HANDLE; +  	nfds = w4ha.size();  	no_burst = 1; @@ -223,7 +278,9 @@ void TaskMan::MainLoop() throw (GeneralException) {  		}  	    } -	    r = poll(ufsd, nfds, (no_burst) && !(Zombies.size()) ? -1: 0); +	    sigprocmask(SIG_UNBLOCK, &sigchildset, 0); +	    r = poll(ufsd, nfds, (no_burst) && !(Zombies.size()) && !(got_sigchild) ? -1: 0); +	    sigprocmask(SIG_BLOCK, &sigchildset, 0);  #else  	    FD_ZERO(readfds);  	    FD_ZERO(writefds); @@ -241,14 +298,16 @@ void TaskMan::MainLoop() throw (GeneralException) {  		FD_SET(p->ha->GetHandle(), exceptfds);  	    } +	    sigprocmask(SIG_UNBLOCK, &sigchildset, 0);  	    r = select(highest + 1, &readfds, &writefds, &exceptfds, NULL); +	    sigprocmask(SIG_BLOCK, &sigchildset, 0);  #endif  	    if (r < 0) {  		if (errno != EINTR) {  		    throw GeneralException(String(_("Error during poll: ")) + strerror(errno));  		}  	    } else if (r == 0) { -		// timeout... +		// timeout or child.  		// **FIXME**  #warning FIXME  	    } else { @@ -294,6 +353,7 @@ void TaskMan::MainLoop() throw (GeneralException) {  				touched = true; +				ehandle = p->ha;  				w4.T->Run();  				if (w4.T->GetState() == TASK_DONE) { @@ -316,9 +376,13 @@ void TaskMan::MainLoop() throw (GeneralException) {  #endif  	} +	/* And finally, let's clean-up all the zombies around here. */ +	  	int no_zombies;  	no_zombies = 0; +	event = E_TASK; +	  	while (!no_zombies) {  	    no_zombies = 1;  	    while (Zombies.size()) { @@ -331,6 +395,7 @@ void TaskMan::MainLoop() throw (GeneralException) {  		if ((o = t->WaitedBy())) {  		    cerr << "-=- TaskMan: running task " << o->GetName() << " for task " << t->GetName() << endl; +		    etask = t;  		    o->Run();  		    if (o->GetState() == TASK_DONE) { @@ -350,9 +415,27 @@ void TaskMan::MainLoop() throw (GeneralException) {  	    }  	} +	/* To end up the loop, let's recall task waiting for processes */ +	 +	event = E_PROCESS; +	  	if (got_sigchild) { -	    // **FIXME** -#warning FIXME +	    for (vector<w4pr_t>::iterator p = w4pr.begin(); p && (p != w4pr.end()); p++) { +		if (p->flag) { +		    Task * t; +		    if (p->T->IsStopped()) { +			continue; +		    } +		    eprocess = p->pr; +		    estatus = p->status; +		    cerr << "-=- TaskMan: running task " << p->T->GetName() << " for process " << p->pr << " (" << p->status << ")\n"; +		    t = p->T; +		    w4pr.erase(p); +		    got_sigchild--; +		    t->Run(); +		    break; +		} +	    }  	}      }  } diff --git a/lib/Variables.cc b/lib/Variables.cc index 274a4ed..d96cad8 100644 --- a/lib/Variables.cc +++ b/lib/Variables.cc @@ -5,6 +5,12 @@  Variables::Variables(int nb) : Vars(nb), nbvars(nb) { } +Variables::Variables(const Variables & v) : nbvars(v.nbvars) { +    for (int i = 0; i < nbvars; i++) { +	Vars.push_back(v.Vars[i]); +    } +} +  Variables::~Variables() { }  void Variables::SetTo(int i, const String & s) { diff --git a/src/Main.cc b/src/Main.cc index 1436f84..caba9b6 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -21,45 +21,81 @@  InPipe * in; -class ad_t : public Action { +class ad_run : public Task {    public: -      ad_t() : Action("menu6") { } -      virtual ~ad_t() { } -    virtual String GetTitle() { return "Action dynamique"; } -    virtual Task * Do(Variables * v, Variables * hds, Handle * h) { -	String ut, un, shds; -	 -	if (!fork()) { -	    execlp("uptime", "uptime", NULL); -	} -	(*in) >> ut; -	wait(NULL); -	 -	if (!fork()) { -	    execlp("uname", "uname", "-a", NULL); -	} -	(*in) >> un; -	wait(NULL); -	 -	for (int i = 0; i < hds->GetNb(); i++) { -	    shds += (*hds)[i] + "<BR>\n"; -	} -	 -	Action * m = new Message("Action dynamique", -	  String("Vous avez choisi l'action dynamique. L'uptime de la machine est '") + -	  ut + "' et sa définition complète est '" + un + "'<BR><BR><BR>Voici la liste des entêtes:<BR><BR>" + shds, ""); +      ad_run(Variables * av, Variables * ahds, Handle * ah) : v(*av), hds(*ahds), h(ah) { +        SetBurst(); +      } +      virtual ~ad_run() {} +    virtual String GetName() { return "Action dynamique"; } +  protected: +    virtual int Do() throw (GeneralException) {	 +	pid_t p; + +	switch (current) { +	case 0: +	    if (!(p = fork())) { +		execlp("uptime", "uptime", NULL); +	    } +	    current = 1; +	    WaitFor(p); +	    Suspend(TASK_ON_HOLD); + +	case 1:	 +	    (*in) >> ut; +	    if (!(p = fork())) { +		execlp("uname", "uname", "-a", NULL); +	    } +	    current = 2; +	    WaitFor(p); +	    Suspend(TASK_ON_HOLD); -	Task * t = m->Do(v, hds, h); +	case 2: +	    (*in) >> un; +	    for (int i = 0; i < hds.GetNb(); i++) { +		shds += hds[i] + "<BR>\n"; +	    } -	Image * testimg = new Image(100, 100); -	testimg->Prepare(); +	    m = new Message("Action dynamique", +		String("Vous avez choisi l'action dynamique. L'uptime de la machine est '") + +		ut + "' et sa définition complète est '" + un + "'<BR><BR><BR>Voici la liste des entêtes:<BR><BR>" + shds, ""); -	Output * testoutput = new Output("TestImg.tga"); +	    current = 3; +	    WaitFor(m->Do(&v, &hds, h)); +	    Suspend(TASK_ON_HOLD); + +	case 3:	 +	    delete m; +	    testimg = new Image(100, 100); +	    testimg->Prepare(); -	new CopyJob(testimg, testoutput, -1, true, true); +	    testoutput = new Output("TestImg.tga"); -	delete m; -	return t; +	    current = 4; +	    WaitFor(new CopyJob(testimg, testoutput, -1, true, true)); +	    Suspend(TASK_ON_HOLD); + +	case 4: +	    return TASK_DONE; +	} +	return TASK_DONE; +    } +  private: +    Variables v, hds; +    Handle * h; +    String ut, un, shds; +    Action * m; +    Image * testimg; +    Output * testoutput; +}; + +class ad_t : public Action { +  public: +      ad_t() : Action("menu6") { } +      virtual ~ad_t() { } +    virtual String GetTitle() { return "Action dynamique"; } +    virtual Task * Do(Variables * v, Variables * hds, Handle * h) { +	return new ad_run(v, hds, h);      }  };  Action * ad = new ad_t(); | 
