diff options
author | Pixel <Pixel> | 2001-11-28 14:59:50 +0000 |
---|---|---|
committer | Pixel <Pixel> | 2001-11-28 14:59:50 +0000 |
commit | 0ddaa5127bf155ffb93f9da13381ad176b43a295 (patch) | |
tree | 8ce67d05aedf5d2e2fcb405e4c4b04facc3d5bad /lib | |
parent | 5212a0752902e64bbd0e24b5c84edb0350e2d3f8 (diff) |
Hopla
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CopyJob.cc | 12 | ||||
-rw-r--r-- | lib/Handle.cc | 6 | ||||
-rw-r--r-- | lib/HttpServ.cc | 20 | ||||
-rw-r--r-- | lib/ReadJob.cc | 10 | ||||
-rw-r--r-- | lib/Task.cc | 6 | ||||
-rw-r--r-- | lib/TaskMan.cc | 67 |
6 files changed, 72 insertions, 49 deletions
diff --git a/lib/CopyJob.cc b/lib/CopyJob.cc index fd31eff..5f348db 100644 --- a/lib/CopyJob.cc +++ b/lib/CopyJob.cc @@ -2,8 +2,9 @@ #include "General.h" CopyJob::CopyJob(Handle * as, Handle * ad, ssize_t asiz, bool ads) : s(as), d(ad), ds(ads), siz(asiz), cursiz(0), r(0) { - WaitFor(s, W4_STICKY | W4_READING); - WaitFor(d, W4_STICKY | W4_WRITING); + s->SetNonBlock(); + d->SetNonBlock(); + WaitFor(s, W4_READING); } CopyJob::~CopyJob() { } @@ -18,17 +19,19 @@ int CopyJob::Do() throw (GeneralException) { r = s->read(buffer, MIN(COPY_BUFSIZ, tr)); } catch (IOAgain e) { + WaitFor(s, W4_READING); Suspend(TASK_ON_HOLD); } - case 1: if (!r) { return TASK_DONE; } + case 1: try { d->write(buffer, r); } catch (IOAgain e) { current = 1; + WaitFor(d, W4_WRITING); Suspend(TASK_ON_HOLD); } current = 0; @@ -36,7 +39,8 @@ int CopyJob::Do() throw (GeneralException) { cursiz += r; if (!s->IsClosed() && (siz != cursiz)) { - throw TaskSwitch(); + WaitFor(s, W4_READING); + Suspend(TASK_ON_HOLD); } if (ds) { diff --git a/lib/Handle.cc b/lib/Handle.cc index 4124231..253ddbf 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -26,7 +26,7 @@ ssize_t Handle::write(const void *buf, size_t count) throw (GeneralException) { done = true; errno = 0; if ((r = ::write(h, buf, count)) < 0) { - if ((!errno) || (errno = EAGAIN)) { + if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus de place libre. Cela peut // arriver si l'on agit sur un pipe ou un handle. Nous @@ -61,7 +61,7 @@ ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) { errno = 0; if ((r = ::read(h, buf, count)) < 0) { - if ((!errno) || (errno = EAGAIN)) { + if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus d'octets. throw IOAgain(); @@ -133,6 +133,8 @@ void Handle::close() { ::close(h); } + h = -1; + closed = 1; } diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc index 602ebe0..ccff319 100644 --- a/lib/HttpServ.cc +++ b/lib/HttpServ.cc @@ -32,7 +32,7 @@ class ProcessRequest : public Task { Action * p; Socket s; - String name; + String name, host; Variables * Vars; bool bad, hasvars, post; }; @@ -60,18 +60,21 @@ int ProcessRequest::Do() { bad = false; - cerr << "---- Got a request\n"; + cerr << "---- Got a request from handle " << s.GetHandle() << " \n"; post = ParseUri(file, domain, &b); len = -1; do { b >> t; - // cerr << "Read Request (n): " << t << endl; + cerr << "Read Request (n): " << t << endl; if ((t.strstr("Content-Length: ") == 0) || (t.strstr("Content-length: ") == 0)) { cerr << "Saw 'Content-Lenght:', reading length from '" << t.extract(16) << "'\n"; len = t.extract(16).to_int(); } + if (t.strstr("Host: ") == 0) { + host = t.extract(6); + } } while (t.strlen()); // cerr << "---- Processing it.\n"; @@ -152,6 +155,7 @@ int ProcessRequest::Do() { try { Handle * i = new Input(String("datas/") + file); SendHeads(&b, GetMime(file), String("Accept-Ranges: bytes") + endhl + "Content-Length: " + (unsigned long long int) i->GetSize() + endhl, i->GetModif()); + i->SetNonBlock(); a = new CopyJob(i, &s); cerr << "File found, dumping.\n"; } @@ -297,8 +301,10 @@ bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) { posslash = Uri.strchr('/'); // Certains navigateurs indiqueront uniquement http://host comme URL. if (posslash >= 0) { + host = Uri.extract(0, posslash - 1); Uri = Uri.to_charp(posslash); } else { + host = Uri; Uri = ""; } } @@ -319,13 +325,13 @@ bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) { void ProcessRequest::SendRedirect(Handle * s) { *s << "HTTP/1.1 301 Moved Permanently" << endhl << "Server: " << name << endhl << - "Location: http://127.0.0.1:" << localport << "/bin/start" << endhl << + "Location: http://" << host << "/bin/start" << endhl << "Cache-Control: no-cache" << endhl << "Connection: closed" << endhl << "Content-Type: text/html" << endhl << endhl << "<HTML><HEAD><TITLE>301 - Moved Permanently</TITLE></HEAD>" << endnl << "<BODY><center><b><h2>You should be redirected to the " << endnl << endnl << - "<a href=\"http://localhost/bin/start\">start page</a></h2></b></center>" << endnl << + "<a href=\"http://" << host << "/bin/start\">start page</a></h2></b></center>" << endnl << "</BODY></HTML>" << endnl; } @@ -346,9 +352,7 @@ void ProcessRequest::SendHeads(Handle * s, const String & mime, const String & e strftime(buf, 1024, "%a, %d %b %Y %H:%M:%S GMT", ft); } *s << "Last-Modified: " << buf << endhl << extra << - "Cache-Control: no-cache" << endhl << - "Keep-Alive: timeout=0, max=0" << endhl << - "Connection: Keep-Alive" << endhl << + "Connection: closed" << endhl << "Content-Type: " << mime << endhl << endhl; } diff --git a/lib/ReadJob.cc b/lib/ReadJob.cc index 3083040..d5cabca 100644 --- a/lib/ReadJob.cc +++ b/lib/ReadJob.cc @@ -2,8 +2,9 @@ #include "HttpServ.h" ReadJob::ReadJob(Handle * as, Handle * ad) : s(as), d(ad) { - WaitFor(s, W4_STICKY | W4_READING); - WaitFor(d, W4_STICKY | W4_WRITING); + s->SetNonBlock(); + d->SetNonBlock(); + WaitFor(s, W4_READING); } ReadJob::~ReadJob() { } @@ -17,6 +18,7 @@ int ReadJob::Do() throw (GeneralException) { *s >> buff; } catch (IOAgain e) { + WaitFor(s, W4_READING); Suspend(TASK_ON_HOLD); } case 1: @@ -25,13 +27,15 @@ int ReadJob::Do() throw (GeneralException) { } catch (IOAgain e) { current = 1; - throw TaskSwitch(); + WaitFor(d, W4_WRITING); + Suspend(TASK_ON_HOLD); } current = 0; if (buff == "") return TASK_DONE; } if (!s->IsClosed()) { + WaitFor(s, W4_READING); Suspend(TASK_ON_HOLD); } diff --git a/lib/Task.cc b/lib/Task.cc index bc7c7a0..72023e4 100644 --- a/lib/Task.cc +++ b/lib/Task.cc @@ -17,20 +17,17 @@ int Task::Do() throw (GeneralException) { } int Task::Run() { - cerr << "==== Task: \"" << GetName() << "\" running.\n"; try { state = Do(); } catch (TaskSwitch) { - cerr << "==== Task: \"" << GetName() << "\" caugh a task switch. returning " << (state == TASK_ON_HOLD ? "TASK_ON_HOLD" : "TASK_DONE") << endl; return state; } catch (GeneralException e) { - cerr << "Task " << GetName() << " caused an unexpected exception. Terminating.\n"; + cerr << "Task " << GetName() << " caused an unexpected exception: \"" << e.GetMsg() << "\". Terminating.\n"; return TASK_DONE; } - cerr << "==== Task: \"" << GetName() << "\" exitted. returning " << (state == TASK_ON_HOLD ? "TASK_ON_HOLD" : "TASK_DONE") << endl; return state; } @@ -51,6 +48,7 @@ void Task::Suspend(int newstate) throw (GeneralException) { } void Task::WaitFor(Handle * h, int flags) { + h->SetNonBlock(); TaskMan::WaitFor(h, this, flags); } 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) { |