AsyncIO *IO = watcher->data;
SetEVState(IO, eDBNext);
- IO->Now = ev_now(event_db);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_db);
EV_syslog(LOG_DEBUG, "%s()", __FUNCTION__);
become_session(IO->CitContext);
SetEVState(IO, eIOAbort);
EV_syslog(LOG_DEBUG, "EVENT Q: %s\n", __FUNCTION__);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
assert(IO->ShutdownAbort);
IO->ShutdownAbort(IO);
}
AsyncIO *IO = watcher->data;
const char *errmsg = NULL;
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
become_session(IO->CitContext);
#ifdef BIGBAD_IODBG
{
AsyncIO *IO = watcher->data;
SetEVState(IO, eIOTimeout);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
ev_timer_stop (event_base, &IO->rw_timeout);
become_session(IO->CitContext);
AsyncIO *IO = watcher->data;
SetEVState(IO, eIOConnfail);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
ev_timer_stop (event_base, &IO->conn_fail);
if (IO->SendBuf.fd != 0)
AsyncIO *IO = watcher->data;
SetEVState(IO, eIOConnfailNow);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
ev_idle_stop (event_base, &IO->conn_fail_immediate);
if (IO->SendBuf.fd != 0)
int err;
SetEVState(IO, eIOConnNow);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
EVM_syslog(LOG_DEBUG, "connect() succeeded.\n");
ev_io_stop(loop, &IO->conn_event);
ssize_t nbytes;
AsyncIO *IO = watcher->data;
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
switch (IO->NextState) {
case eReadFile:
nbytes = FileRecvChunked(&IO->IOB, &errmsg);
AsyncIO *IO = watcher->data;
SetEVState(IO, eCaresFinished);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
EV_syslog(LOG_DEBUG, "event: %s\n", __FUNCTION__);
become_session(IO->CitContext);
assert(IO->DNS.Query->PostDNS);
EVCURLM_syslog(LOG_DEBUG, "request complete\n");
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
ev_io_stop(event_base, &IO->recv_event);
ev_io_stop(event_base, &IO->send_event);
curl_slist_free_all(IO->HttpReq.headers);
+ IO->HttpReq.headers = NULL;
msta = curl_multi_remove_handle(global.mhnd, chnd);
if (msta)
EVCURL_syslog(LOG_ERR,
{
IO->HttpReq.ReplyData = NewStrBufPlain(NULL, SIZ);
}
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
return CurlFillStrBuf_callback(data,
size,
nmemb,
}
SetEVState(IO, eCurlGotIO);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
Action = "";
switch (action)
return;
SetEVState(IO, eCurlShutdown);
- IO->Now = ev_now(event_base);
+ IO->CitContext->lastcmd = IO->Now = ev_now(event_base);
EVCURL_syslog(LOG_DEBUG, "EVENT Curl: %s\n", __FUNCTION__);
curl_slist_free_all(IO->HttpReq.headers);
+ IO->HttpReq.headers = NULL;
msta = curl_multi_remove_handle(global.mhnd, IO->HttpReq.chnd);
if (msta)
{
assert(IO->ShutdownAbort);
IO->ShutdownAbort(IO);
}
+
eNextState
evcurl_handle_start(AsyncIO *IO)
{
Ctx = h->IO->CitContext;
become_session(Ctx);
- h->IO->Now = Now;
+ h->IO->CitContext->lastcmd = h->IO->Now = Now;
switch (h->EvAttch(h->IO))
{
case eReadMore:
IOID = h->IO->ID;
if (h->IO->StartDB == 0.0)
h->IO->StartDB = Now;
- h->IO->Now = Now;
+ h->IO->CitContext->lastcmd = h->IO->Now = Now;
SetEVState(h->IO, eDBAttach);
Ctx = h->IO->CitContext;
cprintf("000\n");
}
+/*
+ * check for async io jobs that are stuck (didn't ping back for 10 mins)
+ */
+void dead_io_check(void) {
+ struct CitContext *nptr;
+ int nContexts, i;
+ char real_room[ROOMNAMELEN];
+
+ /* So that we don't keep the context list locked for a long time
+ * we create a copy of it first
+ */
+ nptr = CtdlGetContextArray(&nContexts) ;
+ if (!nptr)
+ {
+ /* Couldn't malloc so we have to bail but stick to the protocol */
+ return;
+ }
+
+ time_t now = time(NULL);
+ time_t idle;
+
+ for (i=0; i<nContexts; i++)
+ {
+ if ((nptr[i].state != CON_SYS) || (nptr[i].IO == NULL) || (nptr[i].lastcmd == 0))
+ continue;
+
+ if (nptr[i].kill_me != 0)
+ continue;
+ idle = now - nptr[i].lastcmd;
+ if (idle < 600)
+ continue;
+
+ GenerateRoomDisplay(real_room, &nptr[i], CC);
+
+ syslog(LOG_WARNING,
+ "Found stuck event context: CC[%d] "
+
+ "Username: '%s' "
+ "Room: '%s' "
+ "while talking to host: '%s' "
+ "Status: '%s' "
+ "stuck in IO State: '%s' "
+
+ "idle since: %d:%d "
+ "Triggering context termination now!",
+
+ nptr[i].cs_pid,
+
+ nptr[i].curr_user,
+ real_room,
+ nptr[i].cs_host,
+ nptr[i].cs_clientname,
+ nptr[i].lastcmdname,
+
+ (int) idle / 60,
+ (int) idle % 60);
+
+ CtdlTerminateOtherSession(nptr[i].cs_pid);
+ }
+
+ /* release out copy of the context list */
+ free(nptr);
+
+}
/*
* Masquerade roomname
CtdlRegisterProtoHook(cmd_rchg, "RCHG", "Masquerade roomname");
CtdlRegisterProtoHook(cmd_uchg, "UCHG", "Masquerade username");
CtdlRegisterProtoHook(cmd_stel, "STEL", "Enter/exit stealth mode");
+ CtdlRegisterSessionHook(dead_io_check, EVT_TIMER, PRIO_QUEUE + 50);
+
}
/* return our module name for the log */