summaryrefslogtreecommitdiff
path: root/lib/TaskMan.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/TaskMan.cc')
-rw-r--r--lib/TaskMan.cc111
1 files changed, 97 insertions, 14 deletions
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;
+ }
+ }
}
}
}