// returns the filename for a save file given it's number const char *GetProfileName(int num) { if (num == 0) return "profile.dat"; else return stprintf("profile%d.dat", num+1); }
/** @brief handles close syscall at the entrance and the exit Close a file descriptor */ void syscall_close(reg_s * reg, process_descriptor_t * proc) { if (proc_entering(proc)) { proc_inside(proc); } else { if (reg->ret == 0){ proc_outside(proc); int fd = reg->arg[0]; process_close_call(proc, fd); if(strace_option) { stprintf(proc,"close(%d)",fd); stprintf_tabto(proc); stprintf(proc,"= %lu",reg->ret); stprintf_eol(proc); } } if (strace_option) print_close_syscall(reg, proc); } }
void ReaderTask(int fd, const char *id) { time_t dtime = 0; time_t ltime = 0; time_t itime = 0; time_t ftime = 0; time_t atime = 0; int counter = 0; int forceallcheck = 0; int check_disconn_counter = 0; TFd = fd; /* * [re]open RTStatus */ RTStatusOpen(RTStatus, ThisReaderFork * DOpts.ReaderThreads + 1, DOpts.ReaderThreads); /* * Since we setuid(), we won't core. This is for debugging */ if (CoreDebugOpt || (DOpts.ReaderCrashHandler != NULL && strcasecmp(DOpts.ReaderCrashHandler, "none") != 0)) { signal(SIGSEGV, sigSegVReader); signal(SIGBUS, sigSegVReader); signal(SIGFPE, sigSegVReader); signal(SIGILL, sigSegVReader); } signal(SIGHUP, sigHup); signal(SIGUSR1, sigUsr1); /* * Setup thread for passed pipe */ ResetThreads(); AddThread("reader", fd, -1, THREAD_READER, -1, 0); FD_SET(fd, &RFds); /* * Open KPDB database for active file */ if ((KDBActive = KPDBOpen(PatDbExpand(ReaderDActivePat), O_RDWR)) == NULL) { logit(LOG_CRIT, "Unable to open %s", PatDbExpand(ReaderDActivePat)); sleep(60); exit(1); } LoadExpireCtl(1); /* * Only startup connections to backend spools for reader threads */ if (!FeedOnlyServer) CheckServerConfig(time(NULL), 1); /* * Selection core */ while (!TerminatePending || NReadServAct || NumReaders) { /* * select core */ struct timeval tv; fd_set rfds = RFds; fd_set wfds = WFds; fd_set read_only_to_find_eof_fds; int i, sel_r; if (TerminatePending) { if (TerminateTime == 0) TerminateTime = time(NULL) + 2; if (TerminateTime < time(NULL) || !NumReaders) CanTerminate = 1; } /* * Get next scheduled timeout, no more then 2 seconds * (x 10 counter counts = 20 seconds max for {d,i,f}time * check) * * If we are terminating, then speed up the select to clear * out the connections. * */ if (TerminatePending) NextTimeout(&tv, 50); else NextTimeout(&tv, 2 * 1000); stprintf("%s readers=%02d spoolsrv=%d/%d postsrv=%d/%d", id, NumReaders, NReadServAct, NReadServers, NWriteServAct, NWriteServers ); /* Check for disconnected clients every 50 times through the loop */ FD_ZERO(&read_only_to_find_eof_fds); if (++check_disconn_counter == 50) { for (i = 0; i < MaxFds; ++i) { if (FD_ISSET(i, &wfds) && (!(FD_ISSET(i, &rfds)))) { FD_SET(i, &rfds); FD_SET(i, &read_only_to_find_eof_fds); } } check_disconn_counter = 0; } #if USE_AIO AIOUnblockSignal(); #endif sel_r = select(MaxFds, &rfds, &wfds, NULL, &tv); #if USE_AIO AIOBlockSignal(); #endif gettimeofday(&CurTime, NULL); if(sel_r < 0 && errno != EINTR) logit(LOG_CRIT, "select error: %s (rfds=0x%x, wfds=0x%x)", strerror(errno), rfds, wfds); /* * select is critical, don't make unnecessary system calls. Only * test the time every 10 selects (20 seconds worst case), and * only check for a new server configuration file every 60 seconds * after the initial load. This may rearrange THREAD_SPOOL and * THREAD_POST threads. * * We do not startup spool/post servers for feed-only forks * * However, flush overview cache even for feed-only forks. */ if (FeedOnlyServer <= 0) { if (++counter == 10) { time_t t = CurTime.tv_sec; if (ltime) { dtime += t - ltime; itime += t - ltime; ftime += t - ltime; atime += t - ltime; } /* * Check for server config change once a minute */ if (dtime < -5 || dtime >= 5) { if (!TerminatePending) CheckServerConfig(t, ServersTerminated); dtime = 0; } /* * Flush overview every 30 seconds to allow dexpireover to work */ if (ftime < -5 || ftime >= 30) { FlushOverCache(); LoadExpireCtl(0); ftime = 0; } /* * Poll all active descriptors once every 5 minutes. This * will work around a linux embrionic close bug that * doesn't wakeup select(), and is used to idle-timeout * connections. XXX */ if (itime < -5 || itime >= 300) { rfds = RFds; itime = 0; } /* * Force a check all of FD's every 30 seconds to handle * idle and session timeouts */ if (atime < -5 || atime >= 30) { forceallcheck = 1; atime = 0; } ltime = t; counter = 0; } } else { /* * For a feed-only server, we only flush the overview FD * cache every 5 minutes, and with a greater granularity. * It should cycle much faster than that normally, and this * is to prevent idle feed-only forks from keeping locks. * */ if (++counter == 10) { time_t t = CurTime.tv_sec; if (ltime) { ftime += t - ltime; } if (ftime < -5 || ftime >= 300) { FlushOverCache(); ftime = 0; } ltime = t; counter = 0; } } for (i = 0; i < MaxFds; ++i) { if (FD_ISSET(i, &rfds) && FD_ISSET(i, &read_only_to_find_eof_fds)) { char junk_byte; int ret_val; /* * This FD is not marked for reading, but select() claims * it has something to say. We don't actually want to read * from it, but we do want to close it if the associated * connection is dead. */ FD_CLR(i, &rfds); /* Use recv() with MSG_PEEK to see if it's closed. * We shouldn't block because we're O_NONBLOCK. */ ret_val = recv(i, &junk_byte, 1, MSG_PEEK); /* If ret_val is zero, this means the socket is closed. * Blast it. Otherwise, ignore it. */ if(ret_val == 0) { ForkDesc *desc; if((desc = FindThread(i, -1)) != NULL) { Connection *conn = desc->d_Data; if(conn) { NNTerminate(conn); DeleteConnection(conn); } DelThread(desc); } } } } for (i = 0; i < MaxFds; ++i) { if (forceallcheck || TerminatePending || FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds)) { ForkDesc *desc; if ((desc = FindThread(i, -1)) != NULL) { Connection *conn = desc->d_Data; if (conn) { /* * handle output I/O (optimization) */ MBFlush(conn, &conn->co_TMBuf); conn->co_FCounter = 0; } /* * Function dispatch */ switch(desc->d_Type) { case THREAD_READER: if (FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds)) HandleReaderMsg(desc); break; case THREAD_NNTP: /* client */ conn->co_Func(conn); if (conn->co_Auth.dr_ResultFlags & DR_REQUIRE_DNS) { /* Go back to parent for DNS check */ conn->co_Auth.dr_Code = 0; conn->co_TMBuf.mh_WEof = 1; } break; case THREAD_SPOOL: /* spool server */ case THREAD_POST: /* posting server */ conn->co_Func(conn); LogServerInfo(conn, TFd); break; default: /* panic */ break; } /* * do not call MBFlush after the function because the * function may be waiting for write data to drain and * we don't want to cause write data to drain here and * then not get a select wakeup later. * * check for connection termination */ if (conn) { int idleTimeout = 0; if (conn->co_Auth.dr_ReaderDef) { if (conn->co_Auth.dr_ReaderDef->rd_IdleTimeout && conn->co_LastActiveTime + conn->co_Auth.dr_ReaderDef->rd_IdleTimeout <= CurTime.tv_sec) { logit(LOG_INFO, "timeout idle %s", conn->co_Auth.dr_Host); MBLogPrintf(conn, &conn->co_TMBuf, "400 %s: Idle timeout.\r\n", conn->co_Auth.dr_VServerDef->vs_HostName ); idleTimeout = 1; NNTerminate(conn); } if (conn->co_Auth.dr_ReaderDef->rd_SessionTimeout && conn->co_SessionStartTime + conn->co_Auth.dr_ReaderDef->rd_SessionTimeout <= CurTime.tv_sec) { logit(LOG_INFO, "timeout session %s", conn->co_Auth.dr_Host); MBLogPrintf(conn, &conn->co_TMBuf, "400 %s: Session timeout.\r\n", conn->co_Auth.dr_VServerDef->vs_HostName ); idleTimeout = 1; NNTerminate(conn); } } if ((!conn->co_Auth.dr_Code && desc->d_Type == THREAD_NNTP) || idleTimeout || (conn->co_RMBuf.mh_REof && conn->co_TMBuf.mh_WEof && conn->co_TMBuf.mh_MBuf == NULL) || (TerminatePending && !(conn->co_Flags & COF_MAYNOTCLOSE)) ) { DeleteConnection(conn); DelThread(desc); } } } } } forceallcheck = 0; (void)ScanTimers(1, 0); if (CanTerminate) break; } RTStatusClose(); KPDBClose(KDBActive); exit(0); }
void stprintf_tabto(process_descriptor_t * proc) { if (proc->curcol < acolumn) stprintf(proc, "%s", acolumn_spaces + proc->curcol); }
/******************************************************************** * [函数名]: insertCurrentTime * [描述]: 日志当前时间 (eg: YYYY-MM-DD hh:mm:ss) * y: year M: month d: day * h: hour m: minute s: second * [修改记录]: * 2015-05-20,littledj: create * 2015-05-20,littledj: 增加自定义格式 ********************************************************************/ void GLogger::insertCurrentTime(tstring format) { if (format.empty()) format = TEXT("** yyyy-MM-dd hh:mm:ss **\n"); time_t tt = time(0); struct tm *lt = localtime(&tt); tchar* ct = new tchar[format.length() + 4]; tchar tmp[5]; tcscpy(ct, format.c_str()); for (size_t i = 0; i < format.size(); i++) { if (tcsncmp(ct + i, TEXT("yyyy"), 4 ) == 0) { stprintf(tmp, TEXT("%04d"), lt->tm_year + 1900); tcsncpy(ct + i, tmp, 4); i += 3; continue; } if (tcsncmp(ct + i, TEXT("MM"), 2) == 0) { stprintf(tmp, TEXT("%02d"), lt->tm_mon + 1); tcsncpy(ct + i, tmp, 2); i++; continue; } if (tcsncmp(ct + i, TEXT("dd"), 2) == 0) { stprintf(tmp, TEXT("%02d"), lt->tm_mday); tcsncpy(ct + i, tmp, 2); i++; continue; } if (tcsncmp(ct + i, TEXT("hh"), 2) == 0 || tcsncmp(ct + i, TEXT("HH"), 2) == 0) { stprintf(tmp, TEXT("%02d"), lt->tm_hour); tcsncpy(ct + i, tmp, 2); i++; continue; } if (tcsncmp(ct + i, TEXT("mm"), 2) == 0) { stprintf(tmp, TEXT("%02d"), lt->tm_min); tcsncpy(ct + i, tmp, 2); i++; continue; } if (tcsncmp(ct + i, TEXT("ss"), 2) == 0) { stprintf(tmp, TEXT("%02d"), lt->tm_sec); tcsncpy(ct + i, tmp, 2); i++; continue; } } tstring msg = formatMsg(PRINT_TYPE::RAW, TEXT("%s"), ct); delete[] ct; if (m_enableColor) output(msg, m_defaultColor); else output(msg); // 保存当前消息 saveToMessagePool(PRINT_TYPE::RAW, msg); }