summaryrefslogtreecommitdiff
path: root/lib/TaskMan.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/TaskMan.cc')
-rw-r--r--lib/TaskMan.cc67
1 files changed, 39 insertions, 28 deletions
diff --git a/lib/TaskMan.cc b/lib/TaskMan.cc
index 4d782a0..cf411cc 100644
--- a/lib/TaskMan.cc
+++ b/lib/TaskMan.cc
@@ -34,6 +34,10 @@ void taskman_sigchild(int sig) {
signal(SIGCHLD, taskman_sigchild);
}
+void taskman_sigpipe(int sig) {
+ signal(SIGPIPE, taskman_sigpipe);
+}
+
int TaskMan::GotChild(pid_t pid, int status) {
int r = 0;
@@ -54,6 +58,7 @@ void TaskMan::Init() throw (GeneralException) {
}
signal(SIGCHLD, taskman_sigchild);
+ signal(SIGPIPE, taskman_sigpipe);
inited = true;
number = 0;
@@ -108,6 +113,7 @@ void TaskMan::RemoveFromWatches(Task * t) {
}
void TaskMan::WaitFor(Handle * h, Task * t, int flags) {
+ h->SetNonBlock();
w4ha.push_back(w4ha_t(h, flags, t));
}
@@ -134,7 +140,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
throw GeneralException("TaskMan: No more task to manage.");
}
- cerr << "==== TaskMan: main loop.\n";
+ cerr << "-=- TaskMan: begin main loop with " << number << " task to manage.\n";
no_burst = 0;
while (!no_burst) {
@@ -144,7 +150,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
Task * t = *p;
if (t->GetState() == TASK_BURST) {
- cerr << "==== TaskMan: running burning task \"" << t->GetName() << "\".\n";
+ 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;
@@ -163,8 +169,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
}
nfds = w4ha.size();
-
- cerr << "==== TaskMan: polling.\n";
+ no_burst = 1;
if (nfds != 0) {
int r;
@@ -179,22 +184,28 @@ void TaskMan::MainLoop() throw (GeneralException) {
#ifdef USE_POLL
ufsd = (struct pollfd *) malloc(nfds * sizeof(struct pollfd));
for (q = ufsd, p = w4ha.begin(); p && (p != w4ha.end()); p++, q++) {
+ p->dirthy = false;
if (p->T->IsStopped()) {
q->fd = 0;
q->events = 0;
} else {
- cerr << "==== TaskMan: adding watch over handle \"" << p->ha->GetName() << "\" for task \"" << p->T->GetName() << "\"\n";
if (p->ha->CanWatch()) {
q->fd = p->ha->GetHandle();
q->events = (p->flags & W4_READING ? POLLIN : 0) | (p->flags & W4_WRITING ? POLLOUT : 0);
} else {
- cerr << "==== TaskMan: handle can't watch, switching task to burst.\n";
p->T->SetBurst();
+ no_burst = 0;
+ if (!(p->flags & W4_STICKY)) {
+ w4ha.erase(p);
+ p--;
+ }
+ q->fd = 0;
+ q->events = 0;
}
}
}
- r = poll(ufsd, nfds, -1);
+ r = poll(ufsd, nfds, (no_burst) && !(Zombies.size()) ? -1: 1);
#else
FD_ZERO(readfds);
FD_ZERO(writefds);
@@ -228,22 +239,21 @@ void TaskMan::MainLoop() throw (GeneralException) {
struct pollfd * q;
int i;
for (q = ufsd, i = 0; i < nfds; i++, q++) {
-
if (q->revents & POLLNVAL) {
throw GeneralException(String("Error with poll, handle ") + q->fd + " invalid.");
}
if (q->revents & POLLERR) {
- throw GeneralException(String("Error condition whith poll, handle ") + q->fd);
+ cerr << "Error condition whith poll, handle " << q->fd << endl;
}
if (q->revents & POLLHUP) {
- cerr << "Handle " << q->fd << " hung up.";
+ cerr << "Handle " << q->fd << " hung up.\n";
// What should I do now?
}
fd = q->fd;
- if (q->revents & (POLLIN | POLLOUT)) {
+ if (q->revents & (POLLIN | POLLOUT | POLLERR | POLLHUP)) {
#else
/* Later perhaps... Let's use poll for now.
The following is independant of the use of select or poll.
@@ -252,33 +262,33 @@ void TaskMan::MainLoop() throw (GeneralException) {
the test "if handle has changed" */
#endif
// We have to look into the handle structure now...
- for (vector<w4ha_t>::iterator p = w4ha.begin(); p && (p != w4ha.end()); p++) {
- if ((p->ha->GetHandle() == fd) && (!p->T->IsStopped())) {
+ bool touched;
+ for (vector<w4ha_t>::iterator p = w4ha.begin(); p && (p != w4ha.end()); p = touched ? w4ha.begin() : p + 1) {
+ touched = false;
+ if ((p->ha->GetHandle() == fd) && (!p->T->IsStopped()) && (p->T->GetState() != TASK_DONE) && (!p->dirthy)) {
// We've got one, launch it.
- bool erased;
+ cerr << "-=- TaskMan: launching task " << p->T->GetName() << " for handle " << p->ha->GetHandle() << endl;
+ w4ha_t w4 = *p;
+ p->dirthy = true;
- cerr << "==== TaskMan: event over handle \"" << p->ha->GetName() << "\"\n";
-
- erased = false;
- p->T->Run();
+ if (!(p->flags & W4_STICKY)) {
+ w4ha.erase(p);
+ }
+
+ touched = true;
+
+ w4.T->Run();
- if (p->T->GetState() == TASK_DONE) {
+ if (w4.T->GetState() == TASK_DONE) {
// This task died, remove it.
- TaskList_t::iterator q = FindTask(p->T);
+ TaskList_t::iterator q = FindTask(w4.T);
if (q) {
TaskList.erase(q);
number--;
- Zombies.push_back(p->T);
- w4ha.erase(p);
- p--;
- erased = true;
+ Zombies.push_back(w4.T);
}
}
- if (!erased && !(p->flags & W4_STICKY)) {
- w4ha.erase(p);
- p--;
- }
}
}
}
@@ -303,6 +313,7 @@ void TaskMan::MainLoop() throw (GeneralException) {
}
if ((o = t->WaitedBy())) {
+ cerr << "-=- TaskMan: running task " << o->GetName() << " for task " << t->GetName() << endl;
o->Run();
if (o->GetState() == TASK_DONE) {