bool
ConnStateData::isOpen() const
{
- return cbdataReferenceValid(this);
+ return cbdataReferenceValid(this) && // XXX: checking "this" in a method
+ fd >= 0 &&
+ !fd_table[fd].closing();
}
ConnStateData::~ConnStateData()
connNoteUseOfBuffer(conn, http->req_sz);
notedUseOfBuffer = true;
- conn->handleRequestBodyData();
-
- if (!request->body_pipe->exhausted())
- conn->readSomeData();
+ conn->handleRequestBodyData(); // may comm_close and stop producing
/* Is it too large? */
goto finish;
}
- context->mayUseConnection(true);
+ if (!request->body_pipe->productionEnded())
+ conn->readSomeData();
+
+ context->mayUseConnection(!request->body_pipe->productionEnded());
}
http->calloutContext = new ClientRequestContext(http);
{
/* Make sure we're not reading anything and we're not closing */
assert(isOpen(fd));
- assert(!fd_table[fd].flags.closing);
+ assert(!fd_table[fd].flags.closing_);
+ // XXX: If we already called commio_finish_callback, the new callback
+ // we are setting here would apply to the next connection with the same FD.
+ assert(!fd_table[fd].flags.close_request);
debugs(5, 4, "comm_read, queueing read for FD " << fd);
}
}
+void
+comm_close_start(int fd, void *data)
+{
+ fde *F = &fd_table[fd];
+
+ F->flags.closing_ = 1;
+
+#if USE_SSL
+
+ if (F->ssl)
+ ssl_shutdown_method(fd);
+
+#endif
+
+}
+
+
void
comm_close_complete(int fd, void *data)
{
fdd_table[fd].close_file = file;
fdd_table[fd].close_line = line;
- if (F->flags.closing)
+ if(F->flags.close_request)
+ return;
+
+ if (F->flags.closing_)
return;
if (shutting_down && (!F->flags.open || F->type == FD_FILE))
PROF_start(comm_close);
- F->flags.closing = 1;
-
-#if USE_SSL
-
- if (F->ssl)
- ssl_shutdown_method(fd);
+ F->flags.close_request = 1;
-#endif
+ AsyncCall::Pointer startCall=commCbCall(5,4, "comm_close_start",
+ CommCloseCbPtrFun(comm_close_start, NULL));
+ typedef CommCloseCbParams Params;
+ Params &startParams = GetCommParams<Params>(startCall);
+ startParams.fd = fd;
+ ScheduleCallHere(startCall);
commSetTimeout(fd, -1, NULL, NULL);
comm_empty_os_read_buffers(fd);
- AsyncCall::Pointer call=commCbCall(5,4, "comm_close_complete",
+ AsyncCall::Pointer completeCall=commCbCall(5,4, "comm_close_complete",
CommCloseCbPtrFun(comm_close_complete, NULL));
- typedef CommCloseCbParams Params;
- Params ¶ms = GetCommParams<Params>(call);
- params.fd = fd;
- ScheduleCallHere(call);
+ Params &completeParams = GetCommParams<Params>(completeCall);
+ completeParams.fd = fd;
+ ScheduleCallHere(completeCall);
PROF_stop(comm_close);
}
void
comm_write(int fd, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func)
{
- assert(!fd_table[fd].flags.closing);
+ assert(!fd_table[fd].flags.closing_);
debugs(5, 5, "comm_write: FD " << fd << ": sz " << size << ": asynCall " << callback << ".");
return sock;
}
-// AcceptFD::callback() wrapper
void
comm_accept(int fd, IOACB *handler, void *handler_data) {
debugs(5, 5, "comm_accept: FD " << fd << " handler: " << (void*)handler);
if (newfd == COMM_NOMESSAGE) {
/* register interest again */
- debugs(5, 5, "AcceptFD::acceptOne eof: FD " << fd <<
+ debugs(5, 5, HERE << "try later: FD " << fd <<
" handler: " << *theCallback);
commSetSelect(fd, COMM_SELECT_READ, comm_accept_try, NULL, 0);
return false;
memset(this, 0, sizeof(fde));
local_addr.SetEmpty(); // IPAddress likes to be setup nicely.
}
+
+ /**
+ * Return true if the the comm_close for this fd called.
+ * Two flags used for the filedescriptor closing procedure:
+ * - The flag flags.close_request which set when the comm_close called
+ * - The flag flags.closing which scheduled to be set just before the
+ * comm_close handlers called.
+ */
+ bool closing() {return flags.closing_ || flags.close_request;}
/* NOTE: memset is used on fdes today. 20030715 RBC */
static void DumpStats (StoreEntry *);
unsigned int open:1;
unsigned int close_request:1;
unsigned int write_daemon:1;
- unsigned int closing:1;
+ unsigned int closing_:1;
unsigned int socket_eof:1;
unsigned int nolinger:1;
unsigned int nonblocking:1;